Работа с SVG-путями в Python

Краткий ответ: Чтобы работать с SVG-путями в Python, загрузите файл с SVGDocument, найдите элемент <path> через Element.query_selector(), замените его атрибут d с set_attribute() и сохраните отредактированный 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 хранятся в атрибуте d элемента <path>. Он содержит команды рисования, такие как M для перемещения, L для линии, C для кубической кривой Безье, Q для квадратичной кривой и Z для закрытия пути. Изменение этого значения меняет фактическую геометрию пути, а не только его отрисованное положение.

Используйте редактирование path data, когда нужно изменить сам контур. Если нужно только переместить, повернуть или масштабировать существующую фигуру, используйте атрибут transform. Рабочие процессы transform описаны в статье Перемещение, вращение и масштабирование SVG-элементов в Python.

Основы редактирования path data

Самый безопасный рабочий процесс – заменить все значение d известной корректной строкой path data. Это полезно для иконок, генерируемых диаграмм, простых меток и шаблонных SVG-файлов, где элемент <path> имеет стабильный ID.

ЗадачаЧто редактироватьКогда использовать
Изменить контур <path>Атрибут dГеометрия фигуры должна измениться
Переместить или масштабировать тот же контурАтрибут transformФигура должна сохранить исходные координаты
Сгенерировать path data из параметров фигурыАтрибут d, построенный из координат, размеров или точекПользовательский ввод проще задавать как значения фигуры, а не как команды path data
Перекрасить или изменить стиль <path>fill, stroke, styleМеняется только внешний вид

Как редактировать SVG path data в Python

Используйте этот короткий рабочий процесс, когда существующий SVG содержит элемент <path> и нужно изменить его геометрию:

  1. Загрузите SVG-файл с SVGDocument.
  2. Найдите целевой <path> по ID, имени тега или другому стабильному селектору, например через query_selector().
  3. Подготовьте корректное значение d. Можно написать полную строку path data, построить ее из параметров фигуры, таких как координаты, размеры или точки, или добавить известный сегмент в контролируемом шаблоне.
  4. Задайте новые path data с set_attribute(), например set_attribute("d", path_data).
  5. Сохраните отредактированный SVG с document.save() и откройте выходной файл, чтобы проверить новую геометрию.

Примеры ниже следуют тем же шагам, но используют разные источники нового значения 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)

Код меняет геометрию волнообразного <path>. Он не меняет stroke или fill, поэтому визуальный стиль остается прежним, а форма кривой меняется. Изображение ниже сравнивает исходный SVG (a) с path-data-replaced.svg (b).

Исходный SVG и результат после замены SVG path data

Построить path data из координат прямоугольника

Писать атрибут d вручную неудобно, когда входные данные приходят из формы, базы данных, раскладки графика или другой части приложения. Пользователи и данные приложения обычно описывают прямоугольник как x, y, width и height, а не как команды SVG path data.

Следующий пример сохраняет эту удобную для пользователя модель ввода. Он берет координаты прямоугольника, преобразует их в команды path data, записывает эти команды в существующий #marker-path и сохраняет результат как path-data-from-rectangle.svg. Исходный маркер – треугольник, но новая геометрия намеренно генерируется как прямоугольник. Это полезно, когда шаблон должен сохранить элемент <path>, а приложение или пользовательский интерфейс собирает простые значения прямоугольника. Наборы иконок, маски и повторно используемые шаблоны часто ожидают элементы <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)

Код не просит пользователя писать команды M, H, V или Z. Он принимает обычные значения прямоугольника и генерирует из них корректные SVG path data. Существующий <path> сохраняет свои fill, stroke и другие атрибуты, а меняется только геометрия, записанная в d.

Изображение ниже сравнивает исходный SVG (a) с path-data-from-rectangle.svg (b).

Исходный SVG и результат после построения path data из координат прямоугольника

Добавить сегмент path data в контролируемом шаблоне

Можно добавлять команды к существующим path data, когда входной <path> является контролируемым шаблоном и известно, где заканчивается текущий путь. Пример ниже читает текущее значение d у #wave-path, добавляет один линейный сегмент и сохраняет 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)

Используйте этот подход только тогда, когда исходный <path> предсказуем. В произвольных SVG-файлах path data могут содержать относительные команды, несколько subpath, сокращенные команды или закрытые фигуры. В таких случаях безопаснее заменить все значение d или использовать специализированный парсер SVG path data, а не редактировать текст команд по предположению.

Изображение ниже сравнивает исходный SVG (a) и path-data-extended.svg (b). Добавленный линейный сегмент продолжается от конца исходного wave path, поэтому эту технику стоит использовать только тогда, когда конечная точка и контекст команды известны.

Исходный SVG и результат после добавления сегмента к SVG path data

Распространенные ошибки и исправления

ПроблемаИсправление
<path> исчезаетПроверьте, что новое значение d является корректными SVG path data и начинается с команды перемещения, например M
<path> перемещается, но форма не меняетсяВы редактировали transform вместо d; редактируйте d, когда должна измениться сама геометрия
Выходной файл не изменилсяСохраните документ после редактирования и откройте выходной путь, а не входной SVG
Добавленные команды создают странную формуДобавляйте команды только тогда, когда знаете текущую конечную точку <path> и тип команды; иначе заменяйте все значение d
Прямоугольник появляется не тамПроверьте значения x, y, width и height перед построением строки d
Кривые выглядят иначе, чем ожидалосьПроверьте, использует ли <path> кубические C, квадратичные Q, smooth S или T, либо относительные команды в нижнем регистре

FAQ

Как редактировать SVG path data в Python?

Загрузите SVG с SVGDocument, найдите целевой элемент <path> и вызовите set_attribute("d", new_path_data). Сохраните документ после обновления атрибута d.

Что такое SVG-атрибут d?

Атрибут d хранит команды path data, которые определяют геометрию элемента <path>. Команды M, L, C, Q и Z описывают перемещения, линии, кривые и закрытые пути.

Редактировать 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 у многих элементов <path>, используйте document.get_elements_by_tag_name("path"), переберите возвращенные элементы и вызовите set_attribute() для каждого.

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