如何用Inkscape将描边转路径时保留圆点适配Fontello字体转换?
解决Inkscape转路径时单维描边圆点失效的问题
问题描述
我这边通过CI流水线自动化处理SVG转字体的流程:先用Inkscape把描边转成路径,再上传到Fontello生成字体。这套流程对大部分SVG(包括设计师自制和网络下载的)都有效,但遇到像heroicons里calendar-days这类用圆角单维描边实现圆点的SVG时会出问题——转路径后圆点会变成4条无填充的线条,完全丢失原本的圆点效果。
当前执行的Inkscape命令如下:
inkscape --actions="select-all;selection-ungroup;select-all;selection-ungroup;select-all;object-stroke-to-path;select-all;object-flip-vertical;" --export-filename=- $i > $WORK_DIR/$i
已尝试的无效方案
- 修改原始SVG:设计师自制的文件可以调整,但第三方下载的SVG(比如heroicons)涉及版权和后续更新,不能直接改动
- SVG Sprites:资源通过CDN分发,存在浏览器跨域限制,无法使用
- svgicons2svgfont本地生成:图标尺寸、位置错误率极高,部分路径混乱,完全不可用
可行解决方案
方案1:调整Inkscape命令,补全描边转填充的步骤
单维描边转路径失效的核心原因是:Inkscape的object-stroke-to-path只会把描边的轮廓转成路径,但不会自动填充内部区域。可以在转路径后添加合并路径和设置填充的步骤,还原圆点效果。
调整后的命令:
inkscape --actions="select-all;selection-ungroup;select-all;selection-ungroup;select-all;object-stroke-to-path;select-all;path-unite;select-all;object-set-fill:black;select-all;object-flip-vertical;" --export-filename=- $i > $WORK_DIR/$i
关键新增操作:
path-unite:把转路径后的描边轮廓合并成闭合路径object-set-fill:black:给闭合路径设置填充(Fontello需要填充区域才能识别为图标有效内容)
方案2:用sed批量替换SVG中的单维描边为圆形
如果不想改动Inkscape的处理逻辑,可以直接在CI脚本中用sed修改SVG文件,把用来做圆点的单维线条替换成圆形路径:
sed -i 's/<line.*stroke-width="\([0-9]*\)".*x1="\([0-9]*\)" y1="\([0-9]*\)" x2="\2" y2="\3"/<circle cx="\2" cy="\3" r="\1" fill="currentColor"\/>/' $i
这个命令会自动识别所有起点和终点完全重合的line元素(也就是用来模拟圆点的单维描边),替换成对应半径的circle元素,同时保留原尺寸和填充颜色。
方案3:写Python脚本针对性处理第三方SVG
针对heroicons这类有固定格式的第三方SVG库,可以写个轻量脚本批量处理圆点:
import xml.etree.ElementTree as ET import os # 注册SVG命名空间 ns = {'svg': 'http://www.w3.org/2000/svg'} ET.register_namespace('', ns['svg']) for svg_file in os.listdir('.'): if not svg_file.endswith('.svg'): continue tree = ET.parse(svg_file) root = tree.getroot() # 查找所有line元素 lines = root.findall('.//svg:line', ns) for line in lines: # 识别起点终点重合的线条(模拟圆点的单维描边) if line.get('x1') == line.get('x2') and line.get('y1') == line.get('y2'): stroke_width = float(line.get('stroke-width', 1)) cx = line.get('x1') cy = line.get('y1') # 创建对应的circle元素 circle = ET.Element('{http://www.w3.org/2000/svg}circle') circle.set('cx', cx) circle.set('cy', cy) circle.set('r', str(stroke_width/2)) circle.set('fill', line.get('stroke', 'black')) # 替换原line元素 root.replace(line, circle) # 保存修改后的SVG tree.write(svg_file, encoding='utf-8', xml_declaration=True)
这个脚本会精准识别SVG中用来做圆点的特殊线条,替换成标准圆形,完美还原原本的视觉效果,且不会改动其他元素。
注意事项
- 方案1的
path-unite可能会影响部分复杂路径,建议先拿小批量SVG测试验证 - 方案2的sed正则仅适配特定格式的line元素,若SVG的代码结构不同,需要调整正则表达式
- 方案3的Python脚本可以根据不同SVG库的特点,修改识别逻辑适配更多场景
内容的提问来源于stack exchange,提问作者Nicos Karalis
相关产品推荐
相关产品推荐

