我正在尝试创建一个重叠的形状数组。但是我很难防止那些形状叠加在另一个上面。
我想我希望它们在一起啮合,如果这有意义的话?
以下是代码:
var overlap_canvas = document.getElementById("overlap");
var overlap_context = overlap_canvas.getContext("2d");
var x = 200;
var y = x;
var rectQTY = 4 // Number of rectangles
overlap_context.translate(x,y);
for (j=0;j<rectQTY;j++){ // Repeat for the number of rectangles
// Draw a rectangle
overlap_context.beginPath();
overlap_context.rect(-90, -100, 180, 80);
overlap_context.fillStyle = 'yellow';
overlap_context.fill();
overlap_context.lineWidth = 7;
overlap_context.strokeStyle = 'blue';
overlap_context.stroke();
// Degrees to rotate for next position
overlap_context.rotate((Math.PI/180)*360/rectQTY);
}
这是我的jsFiddle: http://jsfiddle.net/Q8yjP/
这就是我想要实现的目标:
非常感谢任何帮助或指导!
答案 0 :(得分:6)
您无法指定此行为,但可以实现使用复合模式的算法方法。
如 this demo the result will be like 所示:
定义线宽和你想要绘制的矩形(你可以用你已经得到的循环填充这个数组来计算位置/角度 - 为简单起见,我只是在这里使用硬编码的那些):
var lw = 4,
rects = [
[20, 15, 200, 75],
[150, 20, 75, 200],
[20, 150, 200, 75],
[15, 20, 75, 200]
], ...
我将解释下面的线宽。
/// set line-width to half the size
ctx.lineWidth = lw * 0.5;
在循环中,为第一次绘制添加一个条件,这也是更改复合模式的位置。我们还使用 last 矩形清除画布:
/// loop through the array with rectangles
for(;r = rects[i]; i++) {
ctx.beginPath();
ctx.rect(r[0], r[1], r[2], r[3]);
ctx.fill();
ctx.stroke();
/// if first we do a clear with last rectangle and
/// then change composite mode and line width
if (i === 0) {
r = rects[rects.length - 1];
ctx.clearRect(r[0] - lw * 0.5, r[1] - lw * 0.5, r[2] + lw, r[3] + lw);
ctx.lineWidth = lw;
ctx.globalCompositeOperation = 'destination-over';
}
}
这将绘制矩形,您可以灵活地更改大小,而无需重新计算裁剪。
线宽分别设置为stroke
从中间划线。因此,由于我们后来使用destination-over
模式,这意味着当我们第一次填充时,一半的线将不可见,这将成为目标的一部分,因此笔划只能填充在描边区域之外(您可以反转stroke
和fill
的顺序,但总是会对第一个矩形进行调整。
我们还需要它来计算必须包括(一半)外线的剪辑。
这也是我们最初将它设置为一半的原因,因为第一次绘制整条线 - 否则第一个矩形将具有双倍粗边框。
答案 1 :(得分:1)
唯一的方法是剪切矩形并计算哪个子矩形超过哪一个。但我认为你必须分别绘制边框和内部矩形,因为分离矩形会增加额外的边框。
希望有所帮助
答案 2 :(得分:1)
可悲的是,您想要使用画布在元素的一部分上设置z-index的功能目前不可用。如果您只需要四个矩形对象,您可以执行类似这样的操作,隐藏矩形的一部分以伪造您想要的效果,但这只是硬编码为4个矩形。
var overlap_canvas = document.getElementById("overlap");
var overlap_context = overlap_canvas.getContext("2d");
var x = 200;
var y = x;
var rectQTY = 4 // Number of rectangles
overlap_context.translate(x, y);
for (j = 0; j < rectQTY; j++) { // Repeat for the number of rectangles
// Draw a rectangle
overlap_context.beginPath();
overlap_context.rect(-90, -100, 180, 80);
overlap_context.fillStyle = 'yellow';
overlap_context.fill();
overlap_context.lineWidth = 7;
overlap_context.strokeStyle = 'blue';
overlap_context.stroke();
if (j === 3) {
overlap_context.beginPath();
overlap_context.rect(24, -86, 72, 80);
overlap_context.fillStyle = 'yellow';
overlap_context.fill();
overlap_context.closePath();
overlap_context.beginPath();
overlap_context.moveTo(20, -89.5);
overlap_context.lineTo(100, -89.5);
overlap_context.stroke();
overlap_context.closePath();
overlap_context.beginPath();
overlap_context.moveTo(20.5, -93.1);
overlap_context.lineTo(20.5, 23);
overlap_context.stroke();
overlap_context.closePath();
}
// Degrees to rotate for next position
overlap_context.rotate((Math.PI / 180) * 360 / rectQTY);
}
如果你必须使它变得动态,你可以剪切暗鸭建议的形状,或者你可以尝试创建一个功能,检测一个对象何时重叠,并重绘每个矩形一次(很难做,不知道是否它工作)。也许你可以想出一些方程式来定位元素,这些方程式与我现在硬编码的方式相关,总是根据旋转角度工作,这将是你最好的选择IMO,但我不知道如何做到这一点准确
总的来说,你现在无法真正做到你正在寻找的东西
答案 3 :(得分:0)
使用纯JavaScript ......
<!DOCTYPE html>
<html>
<head></head>
<body>
<canvas id="mycanvas" width="400px" height="400px"></canvas>
<script>
window.onload = function(){
var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');
//cheat - use a hidden canvas
var hidden = document.createElement('canvas');
hidden.width = 400;
hidden.height = 400;
var hiddenCtx = hidden.getContext('2d');
hiddenCtx.strokeStyle = 'blue';
hiddenCtx.fillStyle = 'yellow';
hiddenCtx.lineWidth = 5;
//translate origin to centre of hidden canvas, and draw 3/4 of the image
hiddenCtx.translate(200,200);
for(var i=0; i<3; i++){
hiddenCtx.fillRect(-170, -150, 300, 120);
hiddenCtx.strokeRect(-170, -150, 300, 120);
hiddenCtx.rotate(90*(Math.PI/180));
}
//reset the hidden canvas to original status
hiddenCtx.rotate(90*(Math.PI/180));
hiddenCtx.translate(-200,-200);
//translate to middle of visible canvas
ctx.translate(200, 200);
//repeat trick, this time copying from hidden to visible canvas
ctx.drawImage(hidden, 200, 0, 200, 400, 0, -200, 200, 400);
ctx.rotate(180*(Math.PI/180));
ctx.drawImage(hidden, 200, 0, 200, 400, 0, -200, 200, 400);
};
</script>
</body>
</html>