如何在Canvas中实现任意形状的等厚度边框轮廓?
实现恒定厚度的形状轮廓

问题描述
我希望对任意形状创建一个缩小版本,然后使用负蒙版生成类似原形状轮廓的新图形,且该轮廓的边框厚度保持恒定。据我了解,若不轻微变形缩小后的图形(如改变宽高比)通常无法实现,因此我可接受解决方案带来的微小变形。
我已掌握负蒙版的创建方法:
ctx.globalCompositeOperation = 'source-out'
无需提供Canvas绘制形状的代码,我已有相关实现。当前问题是未对缩小图形变形导致边框厚度不恒定,且我不清楚变形方法。
我想到一种思路:沿原图形外边缘移动,为每个点向内绘制距离恒定的对应点以确定缩小图形的边缘,但不确定如何确保角度正确,是否需使用曲率半径?
无论是数学方案、算法还是可用库,我都愿意了解!
解决方案
1. 多边形形状的偏移算法
如果你的形状是由直线段组成的多边形,核心是计算向内偏移的边与交点:
- 对每条边,计算指向形状内部的单位法线向量,将整条边沿法线方向移动指定的厚度距离,得到偏移后的边。
- 对相邻的两条偏移边,计算它们的交点,这个交点就是缩小后多边形的顶点。
- 特殊情况处理:锐角的偏移边会在形状内部相交,直接取交点;钝角的偏移边可能不相交,需要延长其中一条边来获取交点,或者用圆弧过渡(若允许圆角轮廓)。
2. 平滑曲线形状的处理
如果形状包含贝塞尔曲线(二次/三次),直接偏移控制点会导致曲线变形,推荐两种方式:
- 分段近似法:将贝塞尔曲线拆分成足够多的短直线段,再用多边形偏移算法处理,得到近似的恒定厚度轮廓。
- 专业曲线偏移:使用曲线偏移的数学算法,计算出偏移后的曲线(非贝塞尔曲线,需用多段曲线拟合),或者直接用现成库处理。
3. 实用库推荐
- Clipper2:支持复杂多边形和路径的偏移操作,可设置偏移距离、圆角/斜角过渡,能自动处理自相交等问题,生成恒定厚度的轮廓。
- Paper.js:基于Canvas的矢量图形库,内置
Path.offset()方法,可直接对任意路径进行向内/向外偏移,自动处理曲线和直线的衔接。
4. 数学关键细节
- 任意点的向内偏移方向是该点所在边/曲线的单位法线向量(指向形状内部)。
- 曲线的法线方向由切线方向推导而来:切线垂直方向即为法线,贝塞尔曲线的切线可通过求导公式计算。
- 曲率半径不影响偏移距离(厚度恒定),但曲率过小的尖锐曲线偏移后可能自相交,需要额外裁剪处理。
内容的提问来源于stack exchange,提问作者Sol
相关产品推荐
相关产品推荐

