Masking shapes in HTML5 canvas?

2019-02-02 00:24发布

Apologies if this has been asked elsewhere but it's pretty hard to phrase as it is so I couldn't find anything.

Is there any way to implement masks in canvas?

For example, using shapes only (no images) I draw a house with a window. I also have a shape representing a person. I want that person to appear at the window - but obviously only so much as the window allows should be visible of the person. The rest would be masked.

I thought about emptying the part of the house occupied by the window, such that there was a genuine hole in the layer, which makes the problem easy to solve.

But I'm conscious you can't delete shapes or parts of shapes in canvas, only draw new stuff over old stuff. So in a multi-layered environment (I'm making a game in Kinetic.JS), what exactly can I do?

Sorry if any of this is poorly explained - new to the whole graphic thing.

2条回答
闹够了就滚
2楼-- · 2019-02-02 00:45

You just need to create a clipping path and draw your shape in there. The Mozilla Developer Network is a great starting place for learning canvas. Here's the section on clipping.

I've created a basic fiddle with an example of what I think you are trying to create.

var ctx = document.getElementById('canvas').getContext('2d');
ctx.fillRect(0, 0, 150, 150);

// create a clipping path
ctx.beginPath();
ctx.moveTo(20, 20);
ctx.lineTo(20, 130);
ctx.lineTo(130, 130);
ctx.lineTo(130, 20);
ctx.clip();

// backgroud in clipped area
ctx.fillStyle = "#11c";
ctx.fillRect(0, 0, 150, 150);

// draw shapes inside clipped area
ctx.translate(75, 90);

ctx.fillStyle = '#f00';

ctx.fillRect(-15, -40, 40, 40);
ctx.fillRect(0, 0, 10, 10);
ctx.fillRect(-25, 10, 60, 60);

Hope this helps, good luck with your project!

查看更多
ら.Afraid
3楼-- · 2019-02-02 01:02

You should learn about clipping and compositing soon, but neither of these are what you actually need here.

Instead you need to learn how to make paths using the non-zero winding number rule, which is what HTML5 canvas uses.

If you draw part of your path clockwise and another part counter-clockwise, you can "cut out" shapes from your path.

Here's an example with a window:

http://jsfiddle.net/simonsarris/U5bXf/


edit: Here's a bit of a visualization for you of how the nonzero winding number rule works:

enter image description here

Subpaths are drawn in a direction, and where the paths cross you'll get filled (or not) spaces.

If you put your finger on any part of the figure, and imagine a line going from your finger out into the empty space, that line crosses the path a number of times. If you start at zero and add 1 for every clockwise path, and subtract 1 for every counterclockwise path, the filled areas are all of the areas that have a non-zero number. The numbers for the areas are given in the above diagram.

查看更多
登录 后发表回答