You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 16:22:35