如何将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




