Skip to main content

Compositing and clipping

In all of our previous examples, shapes were always drawn one on top of the other. This is more than adequate for most situations, but it limits the order in which composite shapes are built. We can, however, change this behaviour by setting the globalCompositeOperation property. In addition, the clip property allows us to hide unwanted parts of shapes.

globalCompositeOperationSection

We can not only draw new shapes behind existing shapes but we can also use it to mask off certain areas, clear sections from the canvas (not limited to rectangles like the clearRect() method does) and more.

globalCompositeOperation = type
This sets the type of compositing operation to apply when drawing new shapes, where type is a string identifying which of the twelve compositing operations to use.

See compositing examples for the code of the following examples.

Clipping pathsSection

A clipping path is like a normal canvas shape but it acts as a mask to hide unwanted parts of shapes. This is visualized in the image on the right. The red star shape is our clipping path. Everything that falls outside of this path won't get drawn on the canvas.

If we compare clipping paths to the globalCompositeOperation property we've seen above, we see two compositing modes that achieve more or less the same effect in source-in and source-atop. The most important differences between the two are that clipping paths are never actually drawn to the canvas and the clipping path is never affected by adding new shapes. This makes clipping paths ideal for drawing multiple shapes in a restricted area.

In the chapter about drawing shapes I only mentioned the stroke() and fill() methods, but there's a third method we can use with paths, called clip().

clip()
Turns the path currently being built into the current clipping path.

You use clip() instead of closePath() to close a path and turn it into a clipping path instead of stroking or filling the path.

By default the <canvas> element has a clipping path that's the exact same size as the canvas itself. In other words, no clipping occurs.

clip exampleSection

In this example, we'll use a circular clipping path to restrict the drawing of a set of random stars to a particular region.

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  ctx.fillRect(0, 0, 150, 150);
  ctx.translate(75, 75);

  // Create a circular clipping path
  ctx.beginPath();
  ctx.arc(0, 0, 60, 0, Math.PI * 2, true);
  ctx.clip();

  // draw background
  var lingrad = ctx.createLinearGradient(0, -75, 0, 75);
  lingrad.addColorStop(0, '#232256');
  lingrad.addColorStop(1, '#143778');
  
  ctx.fillStyle = lingrad;
  ctx.fillRect(-75, -75, 150, 150);

  // draw stars
  for (var j = 1; j < 50; j++) {
    ctx.save();
    ctx.fillStyle = '#fff';
    ctx.translate(75 - Math.floor(Math.random() * 150),
                  75 - Math.floor(Math.random() * 150));
    drawStar(ctx, Math.floor(Math.random() * 4) + 2);
    ctx.restore();
  }
  
}

function drawStar(ctx, r) {
  ctx.save();
  ctx.beginPath();
  ctx.moveTo(r, 0);
  for (var i = 0; i < 9; i++) {
    ctx.rotate(Math.PI / 5);
    if (i % 2 === 0) {
      ctx.lineTo((r / 0.525731) * 0.200811, 0);
    } else {
      ctx.lineTo(r, 0);
    }
  }
  ctx.closePath();
  ctx.fill();
  ctx.restore();
}

In the first few lines of code, we draw a black rectangle the size of the canvas as a backdrop, then translate the origin to the center. Next, we create the circular clipping path by drawing an arc and calling clip(). Clipping paths are also part of the canvas save state. If we wanted to keep the original clipping path we could have saved the canvas state before creating the new one.

Everything that's drawn after creating the clipping path will only appear inside that path. You can see this clearly in the linear gradient that's drawn next. After this a set of 50 randomly positioned and scaled stars is drawn, using the custom drawStar() function. Again the stars only appear inside the defined clipping path.


ScreenshotLive sample

Comments

Popular posts from this blog

Using textures in WebGL

Loading textures The first thing to do is add code to load the textures. In our case, we'll be using a single texture, mapped onto all six sides of our rotating cube, but the same technique can be used for any number of textures. Note: It's important to note that the loading of textures follows cross-domain rules; that is, you can only load textures from sites for which your content has CORS approval. See Cross-domain textures below for details. The code that loads the texture looks like this: // // Initialize a texture and load an image. // When the image finished loading copy it into the texture. // function loadTexture(gl, url) {   const texture = gl.createTexture();   gl.bindTexture(gl.TEXTURE_2D, texture);   // Because images have to be download over the internet   // they might take a moment until they are ready.   // Until then put a single pixel in the texture so we can   // use it immediately. When the image has finished downloading   // we'l...

Matrix math for the web

Matrices can be used to represent transformations of objects in space, and are an important tool to use in visualizations on the Web. This article explores how to create matrices and use them with  CSS3 transforms  and the  matrix3d  transform type. While this article uses CSS3 for the ease of explanations, matrices are a core concept used by many different technologies including WebGL and shaders. This article is also available as an  MDN content kit . The live examples use a collection of  utility functions  availabile under a global object named "MDN". What is a transformation matrix? There are many types of matrices, but the ones we are interested in are the 3D transformation matrices. These matrices consist of a set of 16 values arranged in a 4x4 grid. In JavaScript, it is easy to represent a matrix as an array. The typical starting point is to show the identity matrix. When this matrix is multiplied against another point or matrix then the result...

WebGL: 2D and 3D graphics for the web

WebGL (Web Graphics Library) is a JavaScript API for rendering high-performance interactive 3D and 2D graphics within any compatible web browser without the use of plug-ins. WebGL does so by introducing an API that closely conforms to OpenGL ES 2.0 that can be used in HTML5 <canvas> elements. This conformance makes it possible for the API to take advantage of hardware graphics acceleration provided by the user's device. Support for WebGL is present in Firefox 4+, Google Chrome 9+, Opera 12+, Safari 5.1+, Internet Explorer 11+, and Microsoft Edge build 10240+; however, the user's device must also have hardware that supports these features. The WebGL 2 API introduces support for much of the OpenGL ES 3.0 feature set; it's provided through the WebGL2RenderingContext interface. The <canvas> element is also used by the Canvas API to do 2D graphics on web pages.