You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将Canvas中的多个圆形作为一个整体进行描边?

如何将Canvas中的多个圆形作为一个整体进行描边?

嘿,我完全懂你的困扰!你现在用Canvas画了几个圆形,但它们的描边都是各自独立的,连重叠的地方都有多余线条,想要让它们看起来像是一个整体的外轮廓描边,对吧?

先看你当前的问题:你在同一个beginPath()里添加了多个arc后直接调用stroke(),但这样每个圆形的完整轮廓都会被描边,包括它们互相重叠的内部部分,就像这张图里的效果:

多个圆形各自独立描边的效果

而你想要的是类似这样的效果——几个圆拼合在一起,只有外部一圈描边,内部重叠处没有多余线条:

期望的整体描边效果

下面给你两种可行的实现方法:

方法一:利用合成模式实现外轮廓描边

这个方法思路很直观:先填充出多个圆的组合区域,再通过合成模式只保留外部的描边:

// 第一步:绘制并填充多个圆形的组合区域
context.beginPath();
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.fillStyle = "#F9F8F3";
context.fill();

// 第二步:添加整体外轮廓描边
context.save(); // 保存当前绘图状态,避免影响后续绘制
context.globalCompositeOperation = 'source-out'; // 设置合成模式,只显示描边的外部部分
context.lineWidth = 4; // 根据需求调整描边宽度
context.strokeStyle = '#000'; // 设置描边颜色

// 绘制放大后的圆形路径(半径增加描边宽度的一半,让描边居中显示)
context.beginPath();
context.arc(0, height/6*4, width/6 + context.lineWidth/2, 0, Math.PI*2);
context.arc(width/6*1.9, height/6*4.45, width/6*1.25 + context.lineWidth/2, 0, Math.PI*2);
context.arc(width/6*3.75, height, width/6 + context.lineWidth/2, 0, Math.PI*2);
context.arc(width/6*5.5, height/6*4, width/5 + context.lineWidth/2, 0, Math.PI*2);
context.stroke();

context.restore(); // 恢复之前的绘图状态

方法二:利用路径环绕规则抵消内部线条

Canvas默认使用非零环绕规则,如果我们调整部分圆形的绘制方向(顺时针/逆时针),重叠区域的路径会相互抵消,直接描边整个路径就能得到外轮廓:

context.beginPath();
// 顺时针绘制第一个圆
context.arc(0, height/6*4, width/6, 0, Math.PI*2);
// 逆时针绘制第二个圆(最后一个参数设为true),抵消重叠区域
context.arc(width/6*1.9, height/6*4.45, width/6*1.25, Math.PI*2, 0, true);
// 顺时针绘制第三个圆
context.arc(width/6*3.75, height, width/6, 0, Math.PI*2);
// 逆时针绘制第四个圆,抵消重叠区域
context.arc(width/6*5.5, height/6*4, width/5, Math.PI*2, 0, true);

context.fillStyle = "#F9F8F3";
context.fill();
context.strokeStyle = '#000';
context.lineWidth = 4;
context.stroke();

这两种方法都能实现你想要的整体描边效果,你可以根据自己的需求选择哦~

备注:内容来源于stack exchange,提问作者lolpowerluke

火山引擎 最新活动