Canvas image masking / overlapping

Anup picture Anup · Aug 22, 2013 · Viewed 61.2k times · Source

In my project i have to implement one different color image on the other same size and pattern image using canvas and images are not in round or rectangle shapes. That all are in waves shape and it will apply on a single main background image for showing multiple graphics on every onclick function.

Overlapped image should be change in another selected color. My question Is there any way with using canvas from that we can change the image color which is draw by canvas or we need to use different images always and apply with CSS/jQuery.

I read about canvas image masking and overlapping. But cant understand with my images because that are not in square or circle shape then first thing is how i draw multiple wave shapes on a single image. I have no idea about that i searched but fail to search perfect solution.

My need is just draw one wave image on canvas and change its color from on click function and also set an another div with background-image and also more then two canvas will overlapped. Is this possible?

(That means : This functionality is for create or set multiple graphics on a car, for that each graphic image need to set in a canvas and for another graphic need to overlapped on div and first canvas)

Answer

user1693593 picture user1693593 · Aug 22, 2013

The question as it stands is a bit unclear IMO. To give a more general answer that you can apply to a scenario where you need clipping you can use (at least) two approaches:

Method 1 - Using composite mode to clip

Composite mode is the simplest way but also the least flexible as you need to pre-define the clipping mask as an image with a transparent background (usually PNG).

You can either use the solid parts of the image to clip the next drawn thing, or use the transparent areas to fill in.

Here is an approach where we use the solid parts to clip the next drawn shape/image:

/// draw the shape we want to use for clipping
ctx1.drawImage(imgClip, 0, 0);

/// change composite mode to use that shape
ctx1.globalCompositeOperation = 'source-in';

/// draw the image to be clipped
ctx1.drawImage(img, 0, 0);

Here the globalCompositeOperation is changed to source-in which means that the source image (the one we are gonna draw next to destination) will be drawn inside the existing solid data. Nothing will be drawn to transparent areas.

If our clipping mask looks like this (random fair-use from the net):

Clip mask

And our image like this:

Main image

The result will be this:

Composited image

Method 2 - Using a Path to clip

You can also define a Path for the clipping. This is very flexible as you can adjust the path or animate it if you desire.

Note: Just have in mind that clipping using Path is currently a bit "fragile" in the browsers so you should consider using save() and restore() before and after setting and using a clip path as the browsers are unable to reset clip at the moment (restore will restore the default clip = full canvas);

Lets define a simple zig-zag path (this will be your waves in your case):

/// use save when using clip Path
ctx2.save();

ctx2.beginPath();
ctx2.moveTo(0, 20);
ctx2.lineTo(50,0);
/// ... more here - see demo
ctx2.lineTo(400, 20);
ctx2.lineTo(400, 100);
ctx2.lineTo(0, 100);
ctx2.closePath();

/// define this Path as clipping mask
ctx2.clip();

/// draw the image
ctx2.drawImage(img, 0, 0);

/// reset clip to default
ctx2.restore();

Now that we have set the clipping mask using clip anything drawn to the canvas next will be clipped to fit inside that shape (note that we make sure the shape can end where it begun):

Path clipped image