在 Python 中处理 SVG 滤镜

快速回答: 要在 Python 中处理 SVG 滤镜,请用 SVGDocument 加载 SVG,用 query_selector() 找到目标元素,通过 set_attribute() 设置它的 filter 属性,然后保存 SVG。

1from aspose.svg import SVGDocument
2
3with SVGDocument("document.svg") as document:
4    element = document.root_element.query_selector("circle")
5    if element is not None:
6        element.set_attribute("filter", "url(#filter-id)")
7    document.save("filtered.svg")

SVG 滤镜可以创建模糊、阴影、发光、光照和颜色处理等视觉效果。滤镜通常定义在 <defs> 中,并通过 filter="url(#filter-id)" 属性应用到可见元素。在 Aspose.SVG for Python via .NET 中,你通过 SVG DOM 处理滤镜:查找目标元素,创建滤镜 primitive,设置属性,追加节点,并保存编辑后的文件。

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

SVG 滤镜编辑基础

滤镜工作流包含两部分:滤镜定义和滤镜引用。定义位于 <defs> 中,而可见元素通过 ID 指向它。

任务要编辑的 SVG 标记典型 API 模式
应用现有滤镜filter="url(#filter-id)"query_selector() 找到可见元素并设置 filter 属性
创建新滤镜<defs><filter id="..."></filter></defs>create_element_ns() 创建 SVG 元素,并用 append_child() 追加它们
配置模糊或阴影stdDeviationdxdyflood-color 等滤镜 primitive 属性找到 primitive 并更新属性
移除效果可见元素上的 filter 属性remove_attribute() 移除 filter 引用

如何在 Python 中应用 SVG 滤镜

当 SVG 文件需要模糊、阴影、发光或其他滤镜效果时,可以使用这个工作流:

  1. SVGDocument 加载 SVG 文件。
  2. 查找或创建用于存储可复用定义的 <defs> 元素。
  3. 查找或创建具有稳定 id<filter> 元素。
  4. 添加或更新 <feGaussianBlur><feOffset><feDropShadow> 等滤镜 primitives。
  5. filter="url(#filter-id)" 将滤镜应用到可见 SVG 元素。
  6. 保存编辑后的 SVG,并检查渲染输出。

下面的示例使用 svg-filters.svg 作为输入文件。

创建并应用模糊滤镜

滤镜必须先定义,之后可见元素才能使用它。下面的示例在 <defs> 中创建 #blur 滤镜,添加 <feGaussianBlur> primitive,把滤镜应用到圆,并把结果保存为 svg-blur-filter-applied.svg

 1import os
 2from aspose.svg import SVGDocument
 3
 4SVG_NS = "http://www.w3.org/2000/svg"
 5
 6input_folder = "data/"
 7output_folder = "output/"
 8input_path = os.path.join(input_folder, "svg-filters.svg")
 9output_path = os.path.join(output_folder, "svg-blur-filter-applied.svg")
10os.makedirs(output_folder, exist_ok=True)
11
12with SVGDocument(input_path) as document:
13    svg = document.root_element
14    defs = svg.query_selector("defs")
15
16    if defs is None:
17        defs = document.create_element_ns(SVG_NS, "defs")
18        svg.insert_before(defs, svg.first_child)
19
20    blur_filter = document.create_element_ns(SVG_NS, "filter")
21    blur_filter.set_attribute("id", "blur")
22    blur_filter.set_attribute("x", "-20%")
23    blur_filter.set_attribute("y", "-20%")
24    blur_filter.set_attribute("width", "140%")
25    blur_filter.set_attribute("height", "140%")
26
27    gaussian_blur = document.create_element_ns(SVG_NS, "feGaussianBlur")
28    gaussian_blur.set_attribute("in", "SourceGraphic")
29    gaussian_blur.set_attribute("stdDeviation", "3")
30
31    blur_filter.append_child(gaussian_blur)
32    defs.append_child(blur_filter)
33
34    circle = svg.query_selector("circle")
35    if circle is not None:
36        circle.set_attribute("filter", "url(#blur)")
37
38    document.save(output_path)

代码展示 SVG 滤镜工作流所需的两个部分。<filter><feGaussianBlur> 元素定义效果,filter="url(#blur)" 属性把该效果应用到可见圆上。插图比较源 SVG 图像 (a) 与应用模糊后的圆 (b)。

原始 SVG 圆和文本与通过 Python SVG Gaussian blur filter 模糊后的圆对比

创建 Drop Shadow 滤镜

当 SVG 中还没有你需要的效果时,可以创建新滤镜。下一个示例使用 <feDropShadow> 创建 #label-shadow 滤镜,把它追加到 <defs>,并应用到文本标签。

 1import os
 2from aspose.svg import SVGDocument
 3
 4SVG_NS = "http://www.w3.org/2000/svg"
 5
 6input_folder = "data/"
 7output_folder = "output/"
 8input_path = os.path.join(input_folder, "svg-filters.svg")
 9output_path = os.path.join(output_folder, "svg-drop-shadow-filter.svg")
10os.makedirs(output_folder, exist_ok=True)
11
12with SVGDocument(input_path) as document:
13    svg = document.root_element
14    defs = svg.query_selector("defs")
15
16    if defs is None:
17        defs = document.create_element_ns(SVG_NS, "defs")
18        svg.insert_before(defs, svg.first_child)
19
20    shadow_filter = document.create_element_ns(SVG_NS, "filter")
21    shadow_filter.set_attribute("id", "label-shadow")
22    shadow_filter.set_attribute("x", "-20%")
23    shadow_filter.set_attribute("y", "-20%")
24    shadow_filter.set_attribute("width", "150%")
25    shadow_filter.set_attribute("height", "150%")
26
27    drop_shadow = document.create_element_ns(SVG_NS, "feDropShadow")
28    drop_shadow.set_attribute("dx", "6")
29    drop_shadow.set_attribute("dy", "8")
30    drop_shadow.set_attribute("stdDeviation", "2")
31    drop_shadow.set_attribute("flood-color", "#455a64")
32    drop_shadow.set_attribute("flood-opacity", "0.6")
33
34    shadow_filter.append_child(drop_shadow)
35    defs.append_child(shadow_filter)
36
37    label = svg.query_selector("#label")
38    if label is not None:
39        label.set_attribute("filter", "url(#label-shadow)")
40
41    document.save(output_path)

此示例展示滤镜工作流的两个部分:可复用滤镜在 <defs> 中创建,可见文本元素接收 filter="url(#label-shadow)"。如果缺少其中任一部分,阴影都不会出现。插图显示原始标签图像 (a) 以及带 drop shadow 的同一标签 (b)。

原始 SVG 文本与在 Python 中添加 drop shadow filter 后的 SVG 文本对比

编辑现有滤镜属性

滤镜效果由滤镜 primitive 上的属性控制。下面的示例打开由模糊示例创建的 SVG,找到 #blur 内部的 <feGaussianBlur>,并增大它的 stdDeviation 值。

 1import os
 2from aspose.svg import SVGDocument
 3
 4input_folder = "output/"
 5output_folder = "output/"
 6input_path = os.path.join(input_folder, "svg-blur-filter-applied.svg")
 7output_path = os.path.join(output_folder, "svg-filter-attributes-edited.svg")
 8os.makedirs(output_folder, exist_ok=True)
 9
10with SVGDocument(input_path) as document:
11    svg = document.root_element
12    blur = svg.query_selector("#blur feGaussianBlur")
13
14    if blur is not None:
15        blur.set_attribute("stdDeviation", "8")
16
17    document.save(output_path)

输出使用同一个滤镜 ID,但由于 stdDeviation3 改为 8,模糊效果更强。插图比较第一次模糊结果图像 (a) 与编辑滤镜 primitive 后更强的模糊效果 (b)。

SVG 高斯模糊结果与在 Python 中编辑 stdDeviation 后更强模糊的对比

从 SVG 元素中移除滤镜

从可见元素中移除滤镜,与删除滤镜定义不同。下一个示例打开由模糊示例创建的 SVG,只从圆上移除 filter 引用;#blur 定义可以继续留在 <defs> 中供复用。

 1import os
 2from aspose.svg import SVGDocument
 3
 4input_folder = "output/"
 5output_folder = "output/"
 6input_path = os.path.join(input_folder, "svg-blur-filter-applied.svg")
 7output_path = os.path.join(output_folder, "svg-filter-removed.svg")
 8os.makedirs(output_folder, exist_ok=True)
 9
10with SVGDocument(input_path) as document:
11    circle = document.root_element.query_selector("circle")
12
13    if circle is not None and circle.has_attribute("filter"):
14        circle.remove_attribute("filter")
15
16    document.save(output_path)

当某个滤镜不应再影响特定元素,但其他元素可能仍使用同一滤镜定义时,可以使用这种模式。

常见错误和修复

问题修复
滤镜没有显示确认可见元素具有 filter="url(#filter-id)",并且该 ID 存在于 <defs>
阴影或模糊被裁切<filter> 上通过 xywidthheight 扩大滤镜区域
滤镜影响了错误元素filter 属性应用到真正应接收效果的可见形状或组上
编辑 fillstroke 没有改变效果更新滤镜 primitive 属性,例如 stdDeviationflood-colordxdy
重复 filter ID 导致输出混乱使用稳定且唯一的 ID,并同步更新 url(#...) 引用
输出文件没有变化保存编辑后的文档,并打开输出路径,而不是输入 SVG

FAQ

如何在 Python 中应用 SVG 滤镜?

SVGDocument 加载 SVG,找到可见目标元素,并通过 set_attribute() 设置 filter="url(#filter-id)"。被引用的 <filter> 必须存在于 SVG 文档中,通常位于 <defs> 内。

如何创建 SVG 模糊滤镜?

<defs> 中创建 <filter> 元素,添加 <feGaussianBlur> primitive,设置 stdDeviation,然后用 filter="url(#filter-id)" 把滤镜应用到可见元素。

如何在 Python 中给 SVG 添加 drop shadow?

创建包含 <feDropShadow> 等阴影 primitive 的滤镜,设置 dxdystdDeviationflood-color 等属性,把滤镜追加到 <defs>,并用 filter="url(#filter-id)" 应用它。

可以编辑现有 SVG 滤镜属性吗?

可以。找到滤镜 primitive,例如 #blur feGaussianBlur,并更新 stdDeviation 等属性。修改后保存 SVG。

可以不从 defs 中删除定义,只移除滤镜吗?

可以。从可见元素中删除 filter 属性即可。如果其他元素仍在使用该 <filter> 定义,或你想稍后复用它,定义可以继续保留在 <defs> 中。

相关文章