如何在原生Canvas中填充自定义闭合路径的外侧而非内侧区域
实现方案
原生Canvas实现闭合路径外侧填充有两种成熟的实现思路,无需引入第三方库即可完成需求:
方案1:使用evenodd填充规则 + 画布级矩形路径
原理是利用Canvas 2D的奇偶填充规则,先绘制覆盖整个画布的矩形,再叠加自定义闭合路径,填充时自动识别内外区域:
const context = canvas.getContext('2d') const canvasWidth = canvas.width const canvasHeight = canvas.height canvas.addEventListener('mouseup', function (e) { context.closePath(); // 新增覆盖整个画布的矩形路径 context.rect(0, 0, canvasWidth, canvasHeight); // 设置填充色和填充规则 context.fillStyle = 'green'; context.fill('evenodd'); draw = false; });
evenodd填充规则会判断像素点所在的路径层数,画布矩形为最外层,自定义闭合路径为内层,最终填充的就是两层路径之间的外侧区域- 不需要修改原有鼠标绘制路径的逻辑,改动量最小
方案2:使用裁剪(clip)能力实现
如果不想调整填充规则,也可以通过裁剪功能实现需求:
const context = canvas.getContext('2d') const canvasWidth = canvas.width const canvasHeight = canvas.height canvas.addEventListener('mouseup', function (e) { context.closePath(); context.save(); // 保存当前绘图状态 context.clip(); // 将绘制的闭合路径设为裁剪区域 context.clearRect(0, 0, canvasWidth, canvasHeight); // 清空裁剪区域内的内容 context.restore(); // 恢复状态取消裁剪 // 填充整个画布,此时只有原路径外侧会被上色 context.fillStyle = 'green'; context.fillRect(0, 0, canvasWidth, canvasHeight); draw = false; });
- 逻辑直观,不需要理解填充规则的差异
- 如果需要保留画布上原有的其他内容,可以在执行clip操作前将原有内容缓存到离屏Canvas,填充完成后再绘制回来即可
内容的提问来源于stack exchange,提问作者Gregory Kafanov
相关产品推荐
相关产品推荐

