如何计算描边轮廓类SVG图形的最小stroke-width值
计算图标最小stroke-width的高效方案
你遇到的问题本质是计算2D闭合矢量图形的最小壁厚,结合你已有的顶点坐标、切线信息,可按以下步骤实现,几百个顶点的场景耗时不到1ms,准确率可满足需求:
第一步:先做线段预处理降本
- 先对所有顶点做共线抽稀:连续三个顶点的切线角度差小于1°的,直接删除中间顶点,合并为同一条线段,可把线段总数降低30%~70%
- 按线段的法向量方向分组:因为平行线段的法向量角度完全一致,设置0.5°的角度容错阈值,把法向量角度差在阈值内的线段归为同一组,后续仅需要比对同组内的线段,直接把O(n²)的全局比对复杂度降为O(k*m²)(k是分组数,一般不超过20,m是单组线段数)
- 按需求排除尖角区域的线段:你不需要考虑火焰尖端的交叉点,直接把切线夹角小于15°的尖角位置的线段从分组中剔除即可
第二步:修正平行线段距离计算逻辑
你之前用线段中心点到另一条线段的距离计算的方式误差很大,改为投影区间重叠法计算即可解决拱形线段距离偏小的问题:
- 对同组内的两条线段,将四个端点全部投影到该组对应的法向量轴上,得到两个一维的投影区间
- 先判断两个投影区间是否有重叠,无重叠的直接跳过(这种情况的两条线段不在同一个截面位置,距离不是有效壁厚)
- 有重叠的情况下,两个区间的最小差值就是该位置的实际壁厚,不需要考虑线段是否垂直
- 遍历所有有效配对,记录最小的壁厚值,这个值就是你要的最小
stroke-width,示例场景下得到的结果就是1.5px
可选优化方案
如果需要更高的准确率,可引入轻量的多边形偏移校验:把原始路径向内偏移当前计算得到的最小壁厚,如果偏移后的路径没有出现自交,就说明计算结果准确,JavaScript中可直接用polygon-offset这类轻量库实现,不需要引入重依赖。
原有方案的问题说明
- 全局两两比对线段没有做分组优化,导致计算量随顶点数上涨指数提升
- 中心点距离计算没有考虑线段的有效重叠区域,拱形线段的中心点往往不在有效重叠区间内,所以计算结果偏小
- 不需要要求平行线段对呈90度垂直,壁厚计算仅和法向量方向的投影距离有关,和线段本身的朝向无关
内容的提问来源于stack exchange,提问作者Mr.Biscuit
相关产品推荐
相关产品推荐

