简体   繁体   中英

JavaScript canvas clipping shape when out of bounds

What I'm asking for may be extremely easy, but I've been having quite a bit of trouble getting the intended result.

I want a shape (in this example it's squares but should work with other shapes such as circles, etc) to cut itself off when it leaves the bounds of another shape.

Basically, top image is what I want, bottom is what I currently have: http://imgur.com/a/oQkzG

I heard this can be done with globalCompositeOperation, but am looking for any solution that will give the wanted result.

This is the current code, if you can't use JSFiddle:

// Fill the background
ctx.fillStyle = '#0A2E36';
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Fill the parent rect
ctx.fillStyle = '#CCA43B';
ctx.fillRect(100, 100, 150, 150);

// Fill the child rect
ctx.fillStyle = 'red';
ctx.fillRect(200, 200, 70, 70);

// And fill a rect that should not be affected
ctx.fillStyle = 'green';
ctx.fillRect(80, 80, 50, 50);

JSFiddle Link

Since you need some kind of relation between objects - a scene graph -, you should build it now.
From your question, it seems that any child element should be drawn clipped by its parent element.
(Yes composite operation could come to the rescue, but they are handy only when drawing like 2 figures on a cleared background, things get quickly complicated otherwise, and you might have to use a back canvas, so clipping is simpler here.)

I did below a most basic class that handles the rect case, you'll see that it isn't very difficult to build.

The 'scene' is made out of a background Rect, which has two childs, the yellow and the green. And the yellow Rect has a red child.

 var canvas = document.getElementById('cv'); var ctx = canvas.getContext('2d'); function Rect(fill, x, y, w, h) { var childs = []; this.draw = function () { ctx.save(); ctx.beginPath(); ctx.fillStyle = fill; ctx.rect(x, y, w, h); ctx.fill(); ctx.clip(); for (var i = 0; i < childs.length; i++) { childs[i].draw(); } ctx.restore(); } this.addChild = function (child) { childs.push(child); } this.setPos = function (nx, ny) { x = nx; y = ny; } } // background var bgRect = new Rect('#0A2E36', 0, 0, canvas.width, canvas.height); // One parent rect var parentRect = new Rect('#CCA43B', 100, 100, 150, 150); // child rect var childRect = new Rect('red', 200, 200, 70, 70); parentRect.addChild(childRect); // Another top level rect var otherRect = new Rect('green', 80, 80, 50, 50); bgRect.addChild(parentRect); bgRect.addChild(otherRect); function drawScene() { bgRect.draw(); drawTitle(); } drawScene(); window.addEventListener('mousemove', function (e) { var rect = canvas.getBoundingClientRect(); var x = (e.clientX - rect.left); var y = (e.clientY - rect.top); childRect.setPos(x, y); drawScene(); }); function drawTitle() { ctx.fillStyle = '#DDF'; ctx.font = '14px Futura'; ctx.fillText('Move the mouse around.', 20, 24); } 
 <canvas id='cv' width=440 height=440></canvas> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM