JavaScript canvas 超出范围时剪裁形状
JavaScript canvas clipping shape when out of bounds
我要求的可能非常简单,但我在获得预期结果时遇到了很多麻烦。
我想要一个形状(在这个例子中是正方形,但应该与其他形状一起使用,例如圆形等)在离开另一个形状的边界时自行切断。
基本上,上图是我想要的,下图是我目前拥有的:
http://imgur.com/a/oQkzG
我听说这可以通过 globalCompositeOperation 来完成,但我正在寻找能够提供所需结果的任何解决方案。
这是当前代码,如果您不能使用 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);
由于您需要 objects - 场景图 - 之间的某种关系,因此您现在应该构建它。
从你的问题来看,似乎任何 child 元素都应该被其 parent 元素剪裁。
(是的,复合操作可以解决问题,但它们只有在清除背景上绘制 2 个图形时才有用,否则事情会很快变得复杂,你可能不得不使用后退 canvas,所以这里的剪裁更简单.)
我在下面做了一个最基本的 class 来处理 rect 大小写,你会发现它并不难构建。
'scene' 由背景 Rect 组成,它有两个 child,黄色和绿色。黄色的 Rect 有一个红色的 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>
我要求的可能非常简单,但我在获得预期结果时遇到了很多麻烦。
我想要一个形状(在这个例子中是正方形,但应该与其他形状一起使用,例如圆形等)在离开另一个形状的边界时自行切断。
基本上,上图是我想要的,下图是我目前拥有的: http://imgur.com/a/oQkzG
我听说这可以通过 globalCompositeOperation 来完成,但我正在寻找能够提供所需结果的任何解决方案。
这是当前代码,如果您不能使用 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);
由于您需要 objects - 场景图 - 之间的某种关系,因此您现在应该构建它。
从你的问题来看,似乎任何 child 元素都应该被其 parent 元素剪裁。
(是的,复合操作可以解决问题,但它们只有在清除背景上绘制 2 个图形时才有用,否则事情会很快变得复杂,你可能不得不使用后退 canvas,所以这里的剪裁更简单.)
我在下面做了一个最基本的 class 来处理 rect 大小写,你会发现它并不难构建。
'scene' 由背景 Rect 组成,它有两个 child,黄色和绿色。黄色的 Rect 有一个红色的 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>