描边画布元素,就好像它们是一个元素一样

问题描述 投票:0回答:1

我有一个带有多个圆圈的画布,并且想像 1 一样抚摸它们。

如你所见,都是他们自己画的

  context.beginPath();
  context.fillStyle = "#F9F8F3";
  context.arc(0, height/6*4, width/6, 0, Math.PI*2);
  context.arc(width/6*1.9, height/6*4.45, width/6*1.25, 0, Math.PI*2);
  context.arc(width/6*3.75, height, width/6, 0, Math.PI*2);
  context.arc(width/6*5.5, height/6*4, width/5, 0, Math.PI*2);
  context.stroke();

image with all circles being stroked

它应该看起来像这样 example for desired output

javascript html5-canvas
1个回答
0
投票

没有数学

如果您只需要轮廓的视觉表示。

您可以画两次圆圈来获得轮廓,而不是进行所有复杂的数学运算。

第一次用笔划的颜色填充圆圈,并且半径半笔划宽度大于圆圈的半径。

然后设置全局复合操作来清除像素。

ctx.globalCompositeOperation = "destination-out";

然后用小于圆半径的描边宽度一半的半径填充每个圆(清除像素)。

记得将复合操作恢复为默认值。

示例

绘制 10 个随机圆圈的轮廓。

;(()=>{
    const TAU = Math.PI * 2;
    const ctx = canvas.getContext("2d");
    const rI32 = (min, max) => (max - min) * Math.random() + min | 0;
    const Circle = (x, y, rad) => ({x, y, rad});
    const circles = [];
    const strokeWidth = 2;
    const strokeStyle = "#000";

    circles.push(
        Circle(rI32(0, 512), rI32(0, 256), rI32(50, 90)),
        Circle(rI32(0, 512), rI32(0, 256), rI32(50, 90)),
        Circle(rI32(0, 512), rI32(0, 256), rI32(50, 90)),
        Circle(rI32(0, 512), rI32(0, 256), rI32(50, 90)),
        Circle(rI32(0, 512), rI32(0, 256), rI32(50, 90)),
        Circle(rI32(0, 512), rI32(0, 256), rI32(50, 90)),
        Circle(rI32(0, 512), rI32(0, 256), rI32(50, 90)),
        Circle(rI32(0, 512), rI32(0, 256), rI32(50, 90)),
        Circle(rI32(0, 512), rI32(0, 256), rI32(50, 90)),
        Circle(rI32(0, 512), rI32(0, 256), rI32(50, 90)),
    );

    function draw(cirs, style, width) {
        ctx.fillStyle = style;
        ctx.beginPath();
        for (const c of cirs) {
            ctx.moveTo(c.x + c.rad + width * 0.5, c.y);
            ctx.arc(c.x, c.y, c.rad + width * 0.5, 0, TAU);
        }
        ctx.fill();
        ctx.globalCompositeOperation = "destination-out";
        ctx.beginPath();
        for (const c of cirs) {
            ctx.moveTo(c.x + c.rad - width * 0.5, c.y);
            ctx.arc(c.x, c.y, c.rad - width * 0.5, 0, TAU);
        }
        ctx.fill();
        ctx.globalCompositeOperation = "source-over";
    }
    draw(circles, strokeStyle, strokeWidth);    

})();
canvas { border: 2px solid black; }
<canvas id="canvas" width="512" height="256"></canvas>

© www.soinside.com 2019 - 2024. All rights reserved.