Изменение цветов SVG в Python

Краткий ответ: Чтобы изменить цвета SVG в Python, загрузите файл с помощью SVGDocument, найдите элементы через селекторы или поиск по тегам, обновите fill, stroke, style или stop-color с помощью set_attribute() и сохраните отредактированный 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"Задать fill, stroke или другой цветовой атрибут на элементе
Inline stylestyle="fill:#ff0000;stroke:#222"Обновить нужное свойство внутри атрибута style
Gradient stop<stop stop-color="#ff0000">Обновить stop-color у элементов <stop>
Наследуемый стиль группы<g fill="#ff0000">Изменить атрибут группы или переопределить дочерние элементы
CSS-правило<style>.logo { fill: red; }</style>Изменить текст таблицы стилей или перенести правило в inline-атрибуты

Примеры ниже используют DOM-редактирование. Обычно это безопаснее, чем простая замена текста, потому что код нацелен на SVG-элементы и атрибуты, а не на каждую совпавшую строку в файле.

Как изменить цвета SVG в Python

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

  1. Загрузите SVG-файл с помощью SVGDocument.
  2. Определите, где хранится цвет: в fill, stroke, inline style или stop-color.
  3. Найдите целевой элемент или группу элементов с помощью селектора, поиска по тегу или обхода DOM.
  4. Обновите нужный цветовой атрибут или объявление стиля.
  5. Сохраните отредактированный SVG и сравните результат с исходным изображением.

В статье для примеров кода и иллюстраций используется файл change-svg-colors.svg. В нем есть прямые цветовые атрибуты, inline style, наследуемый цвет группы и градиент, поэтому один и тот же входной файл подходит для всей статьи. При запуске примеров используйте его как data/change-svg-colors.svg.

Изменение цветов Fill и Stroke

Используйте этот сценарий, когда SVG хранит цвета напрямую в атрибутах fill или stroke. Пример загружает change-svg-colors.svg, находит первый круг, меняет его fill и stroke и сохраняет результат как новый 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. Обновляет атрибуты fill, stroke и stroke-width с помощью set_attribute().
  4. Сохраняет измененный SVG через SVGDocument.save().

На иллюстрации ниже показан исходный SVG-файл (a) и результат после изменения атрибутов fill, stroke и stroke-width у круга (b). Остальные элементы не изменяются, поэтому хорошо видно, какой эффект дает первый пример.

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

Замена одного цвета во многих элементах

Используйте этот подход, когда нужно заменить одно точное текстовое значение цвета во многих SVG-элементах. Пример меняет каждый атрибут fill или stroke, который точно совпадает со старым цветом.

 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, "пример-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, но не будет считать red, rgb(255,0,0) и #f00 одним и тем же цветом. Если во входном файле используются разные форматы цвета, нормализуйте значения в собственной подготовке или явно обработайте каждую запись.

Изменение цветов в Inline Style

Некоторые SVG-инструменты хранят цвета в атрибуте style, а не в прямых атрибутах fill или stroke. В этом случае обновляйте нужное CSS-объявление, сохраняя остальные части inline style.

 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-related styling, сохраненные в том же атрибуте.

Изменение цветов остановок градиента

Цвета градиента обычно хранятся в элементах <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, "gradient-recolored.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)

Если в градиенте больше остановок, чем цветов в списке, пример повторно использует последний цвет. В рабочем коде можно сопоставлять цвета по offset, позиции в градиенте или существующему значению stop-color.

На иллюстрации ниже сравниваются исходный SVG-градиент (a) и результат после изменения значений stop-color у остановок градиента (b). Круг, элемент с inline style и наследуемый цвет группы остаются без изменений, поэтому изображение показывает именно редактирование градиента.

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

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

ПроблемаВероятная причинаИсправление
Цвет не изменилсяЦвет хранится в style, CSS-правиле, градиенте или родительской группеПроверьте SVG-разметку и обновите реальное место хранения цвета
Изменился только один элементКод использовал query_selector() и нашел только первое совпадениеДля массового обновления атрибутов используйте поиск по тегам, как показано выше. query_selector_all() используйте только для правок, поддерживаемых возвращаемыми узлами, например для обновления текста.
Inline-стили потерялисьВесь атрибут style был перезаписанОбновляйте только нужное CSS-свойство и сохраняйте остальные объявления
Цвет градиента не изменилсяВидимый цвет идет из элементов градиента <stop>Обновите stop-color у <stop> внутри градиента
Совпадающие цвета пропущеныФайл использует разные записи, например red, #f00 или rgb(255,0,0)Обработайте каждый ожидаемый формат цвета или нормализуйте цвета перед сравнением
Выходной файл не изменилсяДокумент не сохранен или открыт не тот файлВызовите document.save(output_path) после правок и проверьте входной путь

FAQ

Как изменить fill color SVG в Python?

Загрузите SVG с помощью SVGDocument, найдите элемент через document.root_element.query_selector() или get_elements_by_tag_name(), затем вызовите element.set_attribute("fill", "#2e86de") и сохраните документ через document.save(output_path).

Как изменить stroke color SVG в Python?

Загрузите SVG с помощью SVGDocument, выберите элемент, который рисует контур, затем вызовите element.set_attribute("stroke", "#1b4f72"). Если контур отсутствует или слишком тонкий, также задайте stroke-width, например element.set_attribute("stroke-width", "4"), и сохраните SVG.

Можно ли заменить один цвет во всем SVG-файле?

Да. Пройдите по нужным элементам и обновите совпадающие значения fill, stroke, style или stop-color. Сравнение как текста работает только тогда, когда запись цвета в SVG совпадает со значением, с которым сравнивает код.

Почему изменение fill не влияет на мой SVG?

Видимый цвет может приходить из inline style, CSS-правила, градиента или наследуемого стиля родителя. Сначала проверьте SVG-разметку, а затем выбирайте способ редактирования.

Можно ли изменить цвета SVG-градиента?

Да. Загрузите SVG с помощью SVGDocument, пройдите по остановкам градиента через document.get_elements_by_tag_name("stop"), обновите каждый элемент <stop> вызовом stop.set_attribute("stop-color", new_color) и сохраните файл через document.save(output_path).

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