在 Python 中修改 SVG 颜色

快速回答: 要在 Python 中修改 SVG 颜色,请用 SVGDocument 加载文件,用选择器或标签名搜索找到元素,通过 set_attribute() 更新 fillstrokestylestop-color,然后保存编辑后的 SVG。

1from aspose.svg import SVGDocument
2
3with SVGDocument("document.svg") as document:
4    circle = document.root_element.query_selector("circle")
5    if circle is not None:
6        circle.set_attribute("fill", "#2e86de")
7        circle.set_attribute("stroke", "#1b4f72")
8    document.save("recolored.svg")

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

SVG 颜色存储在哪里

SVG 颜色可以定义在多个位置。修改文件之前,应先检查标记结构,并选择与原始 SVG 颜色存储方式匹配的编辑方法。

颜色位置示例最合适的编辑方式
Presentation attributefill="#ff0000"在元素上设置 fillstroke 或其他颜色属性
内联 stylestyle="fill:#ff0000;stroke:#222"更新 style 属性中需要的 CSS 属性
渐变 stop<stop stop-color="#ff0000">更新 <stop> 元素上的 stop-color
继承的组样式<g fill="#ff0000">修改组属性,或在子元素上覆盖该值
CSS 规则<style>.logo { fill: red; }</style>编辑样式表文本,或把规则转换为内联属性

下面的示例使用基于 DOM 的编辑方式。这通常比纯文本替换更安全,因为它针对 SVG 元素和属性,而不是文件中每一个匹配字符串。

如何在 Python 中修改 SVG 颜色

当你需要在保留 SVG 结构的同时重新着色时,可以使用这个工作流:

  1. SVGDocument 加载 SVG 文件。
  2. 检查颜色存储位置,例如 fillstroke、内联 stylestop-color
  3. 用选择器、标签名搜索或 DOM 遍历找到目标元素或元素组。
  4. 更新相关颜色属性或样式声明。
  5. 保存编辑后的 SVG,并将输出与源图像进行比较。

本文的代码示例和插图使用示例文件 change-svg-colors.svg。它包含直接颜色属性、内联样式、继承的组颜色和渐变,因此同一个输入文件可以贯穿整篇文章。运行完整示例时,可将它用作 data/change-svg-colors.svg

修改 Fill 和 Stroke 颜色

当 SVG 直接在 fillstroke 属性中存储颜色时,可以使用这个工作流。示例加载 change-svg-colors.svg,找到第一个圆,修改它的填充和描边,并把结果保存为新的 SVG 文件。

 1import os
 2from aspose.svg import SVGDocument
 3
 4input_folder = "data/"
 5output_folder = "output/"
 6input_path = os.path.join(input_folder, "change-svg-colors.svg")
 7output_path = os.path.join(output_folder, "circle-recolored.svg")
 8os.makedirs(output_folder, exist_ok=True)
 9
10with SVGDocument(input_path) as document:
11    svg_element = document.root_element
12    circle = svg_element.query_selector("circle")
13
14    if circle is not None:
15        circle.set_attribute("fill", "#2e86de")
16        circle.set_attribute("stroke", "#1b4f72")
17        circle.set_attribute("stroke-width", "4")
18
19    document.save(output_path)

这段代码执行以下 SVG 颜色编辑步骤:

  1. 将 SVG 文件加载为 SVGDocument
  2. 使用 query_selector() 找到目标元素。
  3. 使用 set_attribute() 更新 fillstrokestroke-width 属性。
  4. 使用 SVGDocument.save() 保存编辑后的 SVG。

下图显示源 SVG 文件 (a) 以及修改圆的 fillstrokestroke-width 属性后的结果 (b)。其他元素保持不变,因此可以清楚看到第一个示例的效果。

原始 SVG 示例以及修改圆的 fill 和 stroke 颜色后的结果

在多个元素中替换指定颜色

当你要在许多 SVG 元素中替换一个完全匹配的文本颜色值时,可以使用这种方法。示例会修改所有与旧颜色完全匹配的 fillstroke 属性。

 1import os
 2from aspose.svg import SVGDocument
 3
 4input_folder = "data/"
 5output_folder = "output/"
 6input_path = os.path.join(input_folder, "change-svg-colors.svg")
 7output_path = os.path.join(output_folder, "sample-blue.svg")
 8os.makedirs(output_folder, exist_ok=True)
 9
10old_color = "#ff0000"
11new_color = "#0057b8"
12
13with SVGDocument(input_path) as document:
14    for element in document.get_elements_by_tag_name("*"):
15        for attribute_name in ("fill", "stroke"):
16            if element.has_attribute(attribute_name):
17                value = element.get_attribute(attribute_name).strip()
18                if value.lower() == old_color.lower():
19                    element.set_attribute(attribute_name, new_color)
20
21    document.save(output_path)

此示例按文本值比较颜色。它会修改 #ff0000#FF0000,但不会把 redrgb(255,0,0)#f00 视为同一种颜色。如果输入文件使用多种颜色写法,请在自己的预处理步骤中规范化这些值,或显式处理每一种写法。

修改内联 Style 属性中的颜色

有些 SVG 工具会把颜色存储在 style 属性中,而不是直接放在 fillstroke 属性中。这种情况下,应更新需要的 CSS 声明,同时保留内联样式中的其他内容。

 1import os
 2from aspose.svg import SVGDocument
 3
 4
 5def set_style_property(style_text, property_name, property_value):
 6    declarations = []
 7    updated = False
 8
 9    for part in style_text.split(";"):
10        part = part.strip()
11        if not part:
12            continue
13        if ":" not in part:
14            declarations.append(part)
15            continue
16
17        name, value = part.split(":", 1)
18        if name.strip().lower() == property_name.lower():
19            declarations.append(f"{name.strip()}: {property_value}")
20            updated = True
21        else:
22            declarations.append(f"{name.strip()}: {value.strip()}")
23
24    if not updated:
25        declarations.append(f"{property_name}: {property_value}")
26
27    return "; ".join(declarations)
28
29
30input_folder = "data/"
31output_folder = "output/"
32input_path = os.path.join(input_folder, "change-svg-colors.svg")
33output_path = os.path.join(output_folder, "badge-recolored.svg")
34os.makedirs(output_folder, exist_ok=True)
35
36with SVGDocument(input_path) as document:
37    badge = document.root_element.query_selector(".badge")
38
39    if badge is not None:
40        style = badge.get_attribute("style")
41        style = set_style_property(style, "fill", "#0f766e")
42        style = set_style_property(style, "stroke", "#134e4a")
43        badge.set_attribute("style", style)
44
45    document.save(output_path)

这个辅助函数只修改指定的样式属性。这样可以避免一个常见错误:代码覆盖整个 style 属性,意外删除同一属性中保存的 opacity、stroke width、font 或 transform 相关样式。

修改渐变 Stop 颜色

渐变颜色通常存储在 <stop> 元素上。要重新着色渐变,应更新 stop-color 属性,而不是修改引用该渐变的形状上的 fill。

 1import os
 2from aspose.svg import SVGDocument
 3
 4input_folder = "data/"
 5output_folder = "output/"
 6input_path = os.path.join(input_folder, "change-svg-colors.svg")
 7output_path = os.path.join(output_folder, "change-svg-gradient-colors.svg")
 8os.makedirs(output_folder, exist_ok=True)
 9
10new_gradient_colors = ["#2563eb", "#22c55e", "#facc15"]
11
12with SVGDocument(input_path) as document:
13    stops = document.get_elements_by_tag_name("stop")
14
15    for index, stop in enumerate(stops):
16        color = new_gradient_colors[min(index, len(new_gradient_colors) - 1)]
17        stop.set_attribute("stop-color", color)
18
19    document.save(output_path)

如果渐变包含的 stop 数量多于列表长度,示例会复用最后一个颜色。在生产代码中,你可以按 stop 的 offset、渐变中的位置或已有 stop-color 值来映射颜色。

下图比较原始 SVG 渐变 (a) 与更新渐变 stop 上 stop-color 值后的结果 (b)。圆、内联样式元素和继承的组填充保持不变,因此图像只聚焦于渐变编辑。

原始 SVG 示例以及修改渐变 stop 颜色后的结果

常见错误和修复

问题可能原因修复
颜色没有变化颜色存储在 style、CSS 规则、渐变或父级组中检查 SVG 标记,并更新真正控制颜色的位置
只有一个元素改变代码使用 query_selector(),只找到了第一个匹配项对大量属性更新,优先使用上面展示的标签名搜索。只有在返回节点支持的编辑中才使用 query_selector_all(),例如文本更新。
内联样式丢失整个 style 属性被覆盖只更新需要的 CSS 属性,并保留其他声明
渐变颜色没有变化可见颜色来自渐变 <stop> 元素更新渐变内部 <stop> 节点上的 stop-color
匹配颜色被跳过文件使用了不同写法,例如 red#f00rgb(255,0,0)处理每一种预期颜色格式,或在比较前规范化颜色
输出文件没有变化编辑后的文档没有保存,或打开了错误的文件编辑后调用 document.save(output_path) 并检查输入路径

FAQ

如何在 Python 中修改 SVG fill 颜色?

SVGDocument 加载 SVG,通过 document.root_element.query_selector()get_elements_by_tag_name() 找到元素,然后调用 element.set_attribute("fill", "#2e86de"),最后用 document.save(output_path) 保存文档。

如何在 Python 中修改 SVG stroke 颜色?

SVGDocument 加载 SVG,选择绘制轮廓的元素,然后调用 element.set_attribute("stroke", "#1b4f72")。如果轮廓缺失或太细,也可以设置 stroke-width,例如 element.set_attribute("stroke-width", "4"),然后保存 SVG。

可以替换整个 SVG 文件中的一种颜色吗?

可以。遍历相关元素,并更新匹配的 fillstrokestylestop-color 值。按文本匹配只在 SVG 中的颜色写法与代码比较值一致时有效。

为什么修改 fill 后 SVG 没有变化?

可见颜色可能来自内联 style、CSS 规则、渐变或继承的父级样式。选择编辑方式之前,应先检查 SVG 标记。

可以修改 SVG 渐变颜色吗?

可以。用 SVGDocument 加载 SVG,通过 document.get_elements_by_tag_name("stop") 遍历渐变 stop,使用 stop.set_attribute("stop-color", new_color) 更新每个 stop,然后用 document.save(output_path) 保存编辑后的文件。

相关文章