Работа с SVG-фильтрами в Python

Краткий ответ: Чтобы работать с SVG-фильтрами в Python, загрузите SVG с помощью SVGDocument, найдите целевой элемент через query_selector(), задайте его атрибут filter через set_attribute() и сохраните 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: вы находите целевые элементы, создаете примитивы фильтра, задаете атрибуты, добавляете узлы и сохраняете отредактированный файл.

В этой статье вы узнаете, как:

Основы редактирования SVG-фильтров

Сценарий работы с фильтром состоит из двух частей: определения фильтра и ссылки на фильтр. Определение находится в <defs>, а видимый элемент ссылается на него по ID.

ЗадачаЧто редактировать в SVGТипичный API-паттерн
Применить существующий фильтрfilter="url(#filter-id)"Найти видимый элемент через query_selector() и задать атрибут filter
Создать новый фильтр<defs><filter id="..."></filter></defs>Создать SVG-элементы через create_element_ns() и добавить их через append_child()
Настроить размытие или теньАтрибуты примитив фильтраs, например stdDeviation, dx, dy, flood-colorНайти primitive и обновить атрибуты
Удалить эффектАтрибут filter на видимом элементеУдалить ссылку на фильтр через remove_attribute()

Как применять SVG-фильтры в Python

Используйте этот сценарий, когда SVG-файлу нужно размытие, тень, свечение или другой эффект фильтра:

  1. Загрузите SVG-файл с помощью SVGDocument.
  2. Найдите или создайте элемент <defs>, где хранятся переиспользуемые определения.
  3. Найдите или создайте элемент <filter> со стабильным id.
  4. Добавьте или обновите примитив фильтраs, например <feGaussianBlur>, <feOffset> или <feDropShadow>.
  5. Примените фильтр к видимому SVG-элементу через filter="url(#filter-id)".
  6. Сохраните отредактированный SVG и проверьте результат рендеринга.

В примерах ниже используется входной файл svg-filters.svg.

Создание и применение фильтра размытия

Фильтр должен быть определен до того, как видимый элемент сможет его использовать. Следующий пример создает фильтр #blur в <defs>, добавляет primitive <feGaussianBlur>, применяет фильтр к кругу и сохраняет результат как 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 с кругом и текстом в сравнении с кругом, размытым SVG Gaussian blur filter в Python

Создание фильтра Drop Shadow

Создавайте новый фильтр, когда в SVG еще нет нужного эффекта. Следующий пример создает фильтр #label-shadow с <feDropShadow>, добавляет его в <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) и ту же подпись с тенью на изображении (b).

Исходный SVG-текст в сравнении с SVG-текстом после добавления drop shadow filter в Python

Редактирование атрибутов существующего фильтра

Эффект фильтра управляется атрибутами примитив фильтраs. Следующий пример открывает SVG, созданный примером с blur, находит <feGaussianBlur> внутри #blur и увеличивает значение 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)

Выходной файл использует тот же filter ID, но размытие становится сильнее, потому что значение stdDeviation изменилось с 3 на 8. Иллюстрация сравнивает первый результат blur на изображении (a) с более сильным размытием после редактирования примитив фильтра на изображении (b).

Результат SVG Gaussian blur в сравнении с более сильным blur после редактирования stdDeviation в Python

Удаление фильтра с SVG-элемента

Удаление фильтра с видимого элемента отличается от удаления определения фильтра. Следующий пример открывает SVG, созданный примером с blur, и удаляет только ссылку 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>
Тень или размытие обрезаетсяУвеличьте область фильтра через x, y, width и height на <filter>
Фильтр влияет не на тот элементПрименяйте атрибут filter к видимой фигуре или группе, которая должна получить эффект
Изменение fill или stroke не меняет эффектОбновите атрибуты примитив фильтра, например stdDeviation, flood-color, dx или dy
Дублирующиеся ID фильтров дают непонятный результатИспользуйте стабильные уникальные IDs и обновляйте ссылки url(#...) соответственно
Выходной файл не изменилсяСохраните отредактированный документ и откройте выходной файл, а не исходный SVG

FAQ

Как применить SVG-фильтр в Python?

Загрузите SVG с помощью SVGDocument, найдите видимый целевой элемент и задайте filter="url(#filter-id)" через set_attribute(). Указанный <filter> должен существовать в SVG-документе, обычно внутри <defs>.

Как создать SVG-фильтр размытия?

Создайте элемент <filter> в <defs>, добавьте primitive <feGaussianBlur>, задайте stdDeviation, затем примените фильтр к видимому элементу через filter="url(#filter-id)".

Как добавить тень к SVG в Python?

Создайте фильтр с примитив тени, например <feDropShadow>, задайте атрибуты dx, dy, stdDeviation и flood-color, добавьте фильтр в <defs> и примените его через filter="url(#filter-id)".

Можно ли редактировать атрибуты существующего SVG-фильтра?

Да. Найдите примитив фильтра, например #blur feGaussianBlur, и обновите атрибуты вроде stdDeviation. После изменения сохраните SVG.

Можно ли удалить фильтр, не удаляя его из defs?

Да. Удалите атрибут filter с видимого элемента. Определение <filter> может остаться в <defs>, если другие элементы все еще используют его или если вы хотите использовать его позже.

Связанные статьи