在 Python 中处理 SVG 路径

快速解答: 要在 Python 中处理 SVG 路径,请使用 SVGDocument 加载文件,使用 Element.query_selector() 查找 <path> 元素,使用 set_attribute() 替换其 d 属性,然后保存编辑后的 SVG。

1from aspose.svg import SVGDocument
2
3with SVGDocument("document.svg") as document:
4    path = document.root_element.query_selector("#wave-path")
5    if path is not None:
6        path.set_attribute("d", "M40 125 C90 65 150 65 200 125 S310 185 370 95")
7    document.save("edited.svg")

在本文中,您将学习如何:

SVG path data 存储在 <path> 元素的 d 属性中。它包含绘图命令,例如 M 表示移动,L 表示直线,C 表示三次贝塞尔曲线,Q 表示二次曲线,Z 表示闭合路径。编辑这个值会改变路径的实际几何形状,而不仅仅是它的渲染位置。

当您需要改变轮廓本身时,请编辑 path data。如果只是移动、旋转或缩放已有形状,请改用 transform 属性。有关变换工作流,请参阅 在 Python 中移动、旋转和缩放 SVG 元素

Path Data 编辑基础

最安全的工作流是用已知有效的路径字符串替换整个 d 值。这适用于图标、生成的图表、简单标记,以及路径具有稳定 ID 的 SVG 模板文件。

任务编辑内容适用场景
改变路径轮廓d 属性形状几何必须改变
移动或缩放同一轮廓transform 属性形状应保留原始坐标
从形状参数生成路径从坐标、尺寸或点构建的 d 属性用户输入用形状值描述比用路径命令更容易
重新着色或修改路径样式fillstrokestyle只有外观发生变化

如何在 Python 中编辑 SVG path data

当已有 SVG 包含 <path> 元素,并且需要改变其几何形状时,请使用以下简短工作流:

  1. 使用 SVGDocument 加载 SVG 文件。
  2. 通过 ID、标签名或其他稳定选择器查找目标 <path>,例如使用 query_selector()
  3. 准备有效的 d 值。您可以编写完整路径字符串,从坐标、尺寸或点等形状参数构建,也可以在受控模板中追加已知片段。
  4. 使用 set_attribute() 设置新的路径数据,例如 set_attribute("d", path_data)
  5. 使用 document.save() 保存编辑后的 SVG,并打开输出文件检查新几何形状。

下面的示例遵循相同步骤,但新 d 值的来源不同。

替换 SVG path data

代码示例使用 python-edit-svg-path-data.svg 作为输入文件。在第一个工作流中,代码查找 #wave-path,用新曲线替换其 d 属性,并将结果保存为 path-data-replaced.svg

 1import os
 2from aspose.svg import SVGDocument
 3
 4input_folder = "data/"
 5output_folder = "output/"
 6input_path = os.path.join(input_folder, "python-edit-svg-path-data.svg")
 7output_path = os.path.join(output_folder, "path-data-replaced.svg")
 8os.makedirs(output_folder, exist_ok=True)
 9
10new_path_data = "M30 140 C85 60 155 80 220 120 S320 180 380 90"
11
12with SVGDocument(input_path) as document:
13    wave_path = document.root_element.query_selector("#wave-path")
14
15    if wave_path is not None:
16        wave_path.set_attribute("d", new_path_data)
17
18    document.save(output_path)

代码改变了波形路径的几何形状。它不修改 strokefill,因此视觉样式保持不变,而曲线形状发生变化。下图比较源 SVG (a) 和 path-data-replaced.svg (b)。

替换 SVG path data 后的原始 SVG 与编辑结果对比

从矩形坐标构建 Path Data

当输入来自表单、数据库、图表布局或应用程序的其他部分时,手写 d 属性很不方便。用户和应用数据通常用 xywidthheight 描述矩形,而不是用 SVG 路径命令。

下一个示例保留这种对用户友好的输入模型。它接收矩形坐标,将其转换为路径命令,把这些命令写入现有 #marker-path,并将结果保存为 path-data-from-rectangle.svg。源标记是三角形,但新几何形状有意生成矩形。当模板必须保留 <path> 元素,而应用程序或用户界面收集的是简单矩形值时,这种方法很有用。图标集、遮罩和可复用模板通常要求使用路径,即使输入数据更容易描述为一个框。

 1import os
 2from aspose.svg import SVGDocument
 3
 4input_folder = "data/"
 5output_folder = "output/"
 6input_path = os.path.join(input_folder, "python-edit-svg-path-data.svg")
 7output_path = os.path.join(output_folder, "path-data-from-rectangle.svg")
 8os.makedirs(output_folder, exist_ok=True)
 9
10rect_x = 60
11rect_y = 20
12rect_width = 80
13rect_height = 60
14
15rect_path_data = (
16    f"M{rect_x} {rect_y} "
17    f"H{rect_x + rect_width} "
18    f"V{rect_y + rect_height} "
19    f"H{rect_x} Z"
20)
21
22with SVGDocument(input_path) as document:
23    marker_path = document.root_element.query_selector("#marker-path")
24
25    if marker_path is not None:
26        marker_path.set_attribute("d", rect_path_data)
27
28    document.save(output_path)

代码不要求用户编写 MHVZ 命令。它接受普通矩形值,并从中生成有效的 SVG path data。现有 <path> 保留其 fillstroke 和其他属性,只有存储在 d 中的几何形状发生改变。

下图比较源 SVG (a) 和 path-data-from-rectangle.svg (b)。

从矩形坐标构建 path data 后的原始 SVG 与编辑结果对比

在受控模板中追加路径片段

当输入路径是受控模板,并且您知道当前路径在哪里结束时,可以向已有 path data 追加命令。下面的示例读取 #wave-path 的当前 d 值,追加一个线段,并保存 path-data-extended.svg

 1import os
 2from aspose.svg import SVGDocument
 3
 4input_folder = "data/"
 5output_folder = "output/"
 6input_path = os.path.join(input_folder, "python-edit-svg-path-data.svg")
 7output_path = os.path.join(output_folder, "path-data-extended.svg")
 8os.makedirs(output_folder, exist_ok=True)
 9
10with SVGDocument(input_path) as document:
11    wave_path = document.root_element.query_selector("#wave-path")
12
13    if wave_path is not None:
14        current_path_data = wave_path.get_attribute("d").strip()
15        wave_path.set_attribute("d", current_path_data + " L395 95")
16
17    document.save(output_path)

只有在源路径可预测时才使用这种方法。对于任意 SVG 文件,path data 可能包含相对命令、多个子路径、简写命令或闭合形状。在这些情况下,替换完整 d 值或使用专门的 SVG 路径解析器,比基于假设编辑命令文本更安全。

下图比较源 SVG (a) 和 path-data-extended.svg (b)。新增线段从原始波形路径的末端继续延伸,因此只有在已知端点和命令上下文时,才应使用这种技术。

向 SVG path data 追加片段后的原始 SVG 与编辑结果对比

常见错误和修复

问题修复
路径消失检查新的 d 值是否为有效 SVG path data,并以 M 等移动命令开头
路径移动了,但形状没有改变您编辑的是 transform 而不是 d;当几何本身必须改变时,请编辑 d
输出文件没有变化编辑后保存文档,并打开输出路径,而不是输入 SVG
追加命令产生奇怪形状只有在知道路径当前端点和命令类型时才追加;否则替换整个 d
矩形输出位置不正确构建 d 字符串前检查 xywidthheight
曲线效果与预期不同检查路径使用的是三次 C、二次 Q、平滑 ST 命令,还是小写相对命令

常见问题

如何在 Python 中编辑 SVG path data?

使用 SVGDocument 加载 SVG,找到目标 <path> 元素,然后调用 set_attribute("d", new_path_data)。更新 d 属性后保存文档。

SVG 的 d 属性是什么?

d 属性存储定义 <path> 元素几何形状的路径命令。MLCQZ 等命令描述移动、直线、曲线和闭合路径。

应该编辑 path data 还是使用 transform?

当实际轮廓必须改变时,请编辑 d。当只需要移动、旋转或缩放已有轮廓,而不重写其坐标时,请使用 transform

可以向已有 SVG path data 追加命令吗?

可以,但只适用于受控输入,即您知道当前端点和命令上下文。对于任意 SVG 文件,请替换完整 d 值,或先解析 path data 再修改。

可以用 query_selector_all() 编辑所有路径吗?

不可以,至少不适用于本文展示的 set_attribute("d", ...) 工作流。在 Aspose.SVG for Python via .NET 中,query_selector_all() 返回的项可能是 Node 对象,而这些对象不提供 set_attribute()。如果要更新多个路径的 d 属性,请使用 document.get_elements_by_tag_name("path"),遍历返回的元素,并对每个元素调用 set_attribute()

相关文章