Site icon Treehouse Blog

Create Vector Masks using the HTML5 Canvas

The HTML5 canvas can be used to create a lot of cool things, like games, video effects, graphs and more. It can also be used to produce some slightly less complex effects, like manipulating images on the page.

In this post we will look at how to use the canvas tag and clipping to create images that aren’t so rectangular.

Setting up the Canvas

In this example, I am going to be using an image of Ryan, and see if I can modify the shape of it, using the canvas.

First we need a canvas tag in our page


This just sets up a simple canvas with the width and height of our image. I chose these dimensions so that it does not take up any more space than is needed.

Next in JavaScript we will get the canvas and its drawing context in JavaScript

// Grab the Canvas and Drawing Context
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');

So now we are ready to begin drawing our image into the canvas.

Drawing the Image into the Canvas

We have our canvas set up, now we need to draw the image into that canvas. We can do this easily, but we need an HTML img element with our image in order to draw it.

We could grab an <img> tag from our page, but we can do it using JavaScript.

// Create an image element
var img = document.createElement('IMG');

// When the image is loaded, draw it
img.onload = function () {
    ctx.drawImage(img, 0, 0);
}

// Specify the src to load the image
img.src = "http://i.imgur.com/gwlPu.jpg";

Run this code

Here we are creating a new element for our image. Since we can’t draw the image until it has been downloaded, we need to wait for onload to draw it. Inside of the onload listener, we call the ctx.drawImage(), and pass it the img element. We also pass 0, 0 meaning we want to draw 0 pixels from the top and left.

Finally we set the src of our image, which triggers the browser to fetch the image data.

Clip that Image

In the canvas, we can use a technique called clipping. We can use a path we define to specify that future operations should only affect the area within the path.

Since the canvas is transparent, if we create a clipping path, and then draw the image, the image will only show up inside the shape of that path.

So let’s draw a circle, clip to that path, and draw the image.

// Create an image element
var img = document.createElement('IMG');

// When the image is loaded, draw it
img.onload = function () {

    // Save the state, so we can undo the clipping
    ctx.save();

    // Create a circle
    ctx.beginPath();
    ctx.arc(106, 77, 74, 0, Math.PI * 2, false);

    // Clip to the current path
    ctx.clip();

    ctx.drawImage(img, 0, 0);

    // Undo the clipping
    ctx.restore();
}

// Specify the src to load the image
img.src = "http://i.imgur.com/gwlPu.jpg";

Run this code

You may notice the ctx.save() and ctx.restore() calls. This is because anything we try to do to the canvas after we clip it will only work within the clipping region. We call save() before we clip and then call restore() after, and the state of the canvas will be restored to before the clipping was applied. Everything you drew will remain, but the clipping definition will be gone.

Go Crazy

You can clip to more than just circles. You can clip to any shape you want. You just need to define your path.

// Create an image element
var img = document.createElement('IMG');

// When the image is loaded, draw it
img.onload = function () {

    // Save the state, so we can undo the clipping
    ctx.save();

    // Create a shape, of some sort
    ctx.beginPath();
    ctx.moveTo(10, 10);
    ctx.lineTo(100, 30);
    ctx.lineTo(180, 10);
    ctx.lineTo(200, 60);
    ctx.arcTo(180, 70, 120, 0, 10);
    ctx.lineTo(200, 180);
    ctx.lineTo(100, 150);
    ctx.lineTo(70, 180);
    ctx.lineTo(20, 130);
    ctx.lineTo(50, 70);
    ctx.closePath();
    // Clip to the current path
    ctx.clip();

    ctx.drawImage(img, 0, 0);

    // Undo the clipping
    ctx.restore();
}

// Specify the src to load the image
img.src = "http://i.imgur.com/gwlPu.jpg";

Run this code

You can use clipping in combination with other techniques to create some pretty interesting effects. What cool effects can you create?

Exit mobile version