Javascript 如何使用画布创建重叠(而不是堆叠)形状?

Javascript 如何使用画布创建重叠(而不是堆叠)形状?,javascript,html,canvas,Javascript,Html,Canvas,我正在尝试创建一组重叠的形状。但我很难阻止这些形状堆叠在一起 我想我想让他们在一起,如果这有意义的话 代码如下: 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.

我正在尝试创建一组重叠的形状。但我很难阻止这些形状堆叠在一起

我想我想让他们在一起,如果这有意义的话

代码如下:

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);
}
var overlap\u canvas=document.getElementById(“overlap”);
var overlap_context=overlap_canvas.getContext(“2d”);
var x=200;
变量y=x;
var rectQTY=4//矩形数
重叠上下文。翻译(x,y);

对于(j=0;j来说,唯一的方法是剪切矩形,并计算出哪个子矩形经过哪个子矩形。但我认为你必须分别绘制边框和内部矩形,因为分隔矩形会增加额外的边框


希望它能有所帮助。遗憾的是,您想要的使用画布在元素的一部分上设置z索引的功能目前还不可用。如果您只需要为四个矩形对象设置z索引,您可以这样做,隐藏部分矩形以伪造您想要的效果,但是这是硬编码的,仅为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);
}
var overlap\u canvas=document.getElementById(“overlap”);
var overlap_context=overlap_canvas.getContext(“2d”);
var x=200;
变量y=x;
var rectQTY=4//矩形数
重叠上下文。翻译(x,y);
对于(j=0;j

如果您必须使其动态化,您可以像建议的那样剪切形状,或者您可以尝试创建一个函数来检测对象何时重叠,并在每个矩形上重新绘制一次(很难做到,也不确定是否可行).也许你能想出一些公式来定位元素,我现在把它们硬编码成始终根据旋转角度工作,这在我看来是你最好的选择,但我不知道如何准确地做到这一点


总的来说,在这个时间点上,你不能真正做到你想要的事情

你不能指定这种行为,但你可以实现一种使用复合模式的算法ish方法

所示:

定义要绘制的线宽和矩形(您可以用已经计算位置/角度的循环填充此数组-为简单起见,我在这里只使用硬编码的循环):

我将在下面解释线宽

/// set line-width to half the size
ctx.lineWidth = lw * 0.5;
在循环中,您为第一次绘制添加了一个条件,这也是您更改合成模式的地方。我们还使用最后一个矩形清除画布:

/// 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';
    }
}
这将绘制矩形,您可以灵活地更改大小,而无需重新计算剪裁

线条宽度单独设置为
笔划
从中间笔划线条。因此,由于我们以后使用
目标覆盖
模式,这意味着当我们第一次填充时,一半线条将不可见,这将成为目标的一部分,因此笔划将只能填充笔划区域之外的区域(您可以颠倒
笔划
填充
的顺序,但始终会对第一个矩形进行调整)

我们还需要它来计算裁剪,其中必须包括(一半)外部的线


这也是我们最初将其设置为一半的原因,因为整条线将在第一次绘制-否则第一个矩形将有两倍厚的边框。

使用纯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>

window.onload=函数(){
var canvas=document.getElementById('mycanvas');
var ctx=canvas.getContext('2d');
//作弊-使用隐藏的画布
var hidden=document.createElement('canvas');
隐藏宽度=400;
隐藏高度=400;
var hiddenCtx=hidden.getContext('2d');
hiddenCtx.strokeStyle='蓝色';
hiddenCtx.fillStyle='黄色';
hiddenCtx.lineWidth=5;
//将原点平移到隐藏画布的中心,并绘制图像的3/4
hiddenCtx.translate(200200);

对于(var i=0;我感谢您。这是一个很大的帮助,非常感谢您的输入。
<!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>