Контуры
Элемент <path> — самый мощный элемент среди базовых фигур в библиотеке SVG. Его можно использовать для создания линий, кривых, дуг и многого другого.
Контуры создают сложные фигуры, объединяя несколько прямых или кривых линий. Сложные фигуры, состоящие только из прямых линий, можно создавать с помощью элементов <polyline>. Хотя элементы <polyline> и <path> позволяют создавать похожие фигуры, для имитации кривых элементам <polyline> требуется множество коротких прямых линий, поэтому они плохо масштабируются до больших размеров.
При создании SVG важно хорошо понимать, как устроены контуры. Хотя создавать сложные контуры с помощью XML-редактора или текстового редактора не рекомендуется, понимание принципов их работы поможет находить и устранять проблемы с отображением SVG.
Фигура элемента <path> определяется одним параметром: d. (Подробнее см. в разделе базовые фигуры.) Атрибут d содержит последовательность команд и параметров, используемых этими командами.
Каждая команда обозначается определённой буквой (например, при создании класса ему задают имя и местоположение). Допустим, нужно переместиться к координатам x и y (10, 10). Команда «Переместить» обозначается буквой M. Когда анализатор встречает эту букву, он понимает, что нужно переместиться к точке. Поэтому, чтобы переместиться к точке (10, 10), нужно использовать команду M 10 10. После этого анализатор начинает искать следующую команду.
У каждой команды есть два варианта. Заглавная буква задаёт абсолютные координаты на странице, а строчная буква — относительные (например, переместиться на 10px вверх и на 7px влево от последней точки).
Координаты в параметре d всегда указываются без единиц измерения и, следовательно, в пользовательской системе координат. Далее мы узнаем, как можно трансформировать контуры для решения других задач.
Команды для рисования линий
Для узлов <path> существует пять команд для рисования линий. Первая команда — «Переместить», или M, описанная выше. Она принимает два параметра: координату (x) и координату (y), к которым нужно переместиться. Если курсор уже находился в какой-либо точке страницы, соединяющая эти позиции линия не рисуется. Команда «Переместить» используется в начале контуров, чтобы задать начальную точку рисования. Например:
M x y (or) m dx dy
В следующем примере есть только точка (10, 10). Однако обратите внимание: при обычном отображении контура она не будет видна. Например:
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"> <path d="M10 10" /> </svg>
Для рисования линий есть три команды. Самая универсальная — команда «Линия до», обозначаемая L. Команда L принимает два параметра — координаты x и y — и рисует линию от текущей позиции до новой.
L x y (or) l dx dy
Для рисования горизонтальных и вертикальных линий есть две сокращённые формы. Команда H рисует горизонтальную линию, а V — вертикальную. Каждая команда принимает только один параметр, поскольку перемещение происходит только в одном направлении.
H x (or) h dx V y (or) v dy
Можно начать с рисования фигуры. Для начала нарисуем прямоугольник (такой же, который проще было бы создать с помощью элемента <rect>). Он состоит только из горизонтальных и вертикальных линий.
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"> <path d="M 10 10 H 90 V 90 H 10 L 10 10" /> </svg>
Объявление контура выше можно немного сократить с помощью команды «Замкнуть контур», обозначаемой Z. Эта команда проводит прямую линию от текущей позиции обратно к первой незамкнутой точке (первой точке после последней команды Z, если она есть, или к первой точке контура в противном случае) и замыкает контур соединением линий. Обычно эту команду ставят в конце узла контура, но не всегда. Между заглавной и строчной формами команды нет различий.
Z (or) z
Таким образом, контур выше можно сократить до следующего вида:
<path d="M 10 10 H 90 V 90 H 10 Z" fill="transparent" stroke="black" />
Для рисования той же фигуры можно также использовать относительные формы этих команд. Относительные команды обозначаются строчными буквами: вместо перемещения курсора к точным координатам они перемещают его относительно последней позиции. Например, поскольку размер нашего прямоугольника составляет 80×80, элемент <path> можно было бы записать так:
<path d="M 10 10 h 80 v 80 h -80 Z" fill="transparent" stroke="black" />
Контур переместится к точке (10, 10), затем на 80 единиц вправо по горизонтали, на 80 единиц вниз, на 80 единиц влево, а затем вернётся в начальную точку.
В этих примерах, вероятно, интуитивнее было бы использовать элементы <polygon> или <polyline>. Однако контуры настолько часто используются при создании SVG, что разработчикам может быть удобнее использовать именно их. Существенной разницы в производительности при использовании того или иного варианта нет.
Команды для рисования кривых
Для создания плавных кривых можно использовать три разные команды. Две из них позволяют строить кривые Безье, а третья — дугу, то есть часть окружности. Возможно, вы уже приобрели практический опыт работы с кривыми Безье, используя инструменты для работы с контурами в Inkscape, Illustrator или Photoshop. Кривых Безье существует бесконечно много, но в элементах <path> доступны только два типа: кубическая кривая, обозначаемая C, и квадратичная, обозначаемая Q.
Кривые Безье
Кубическая кривая C немного сложнее. Для каждой точки кубической кривой Безье задаются две управляющие точки. Поэтому для создания кубической кривой Безье нужно указать три набора координат.
C x1 y1, x2 y2, x y (or) c dx1 dy1, dx2 dy2, dx dy
Последний набор координат (x, y) задаёт конечную точку линии. Два остальных набора задают управляющие точки. (x1, y1) — управляющая точка в начале кривой, а (x2, y2) — в конце. Управляющие точки, по сути, задают наклон линии, выходящей из каждой точки. Затем функция Безье создаёт плавную кривую, которая переходит от наклона, заданного в начале линии, к наклону в её конце.
<svg width="190" height="160" xmlns="http://www.w3.org/2000/svg">
<path d="M 10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent" />
<path d="M 70 10 C 70 20, 110 20, 110 10" stroke="black" fill="transparent" />
<path
d="M 130 10 C 120 20, 180 20, 170 10"
stroke="black"
fill="transparent" />
<path d="M 10 60 C 20 80, 40 80, 50 60" stroke="black" fill="transparent" />
<path d="M 70 60 C 70 80, 110 80, 110 60" stroke="black" fill="transparent" />
<path
d="M 130 60 C 120 80, 180 80, 170 60"
stroke="black"
fill="transparent" />
<path
d="M 10 110 C 20 140, 40 140, 50 110"
stroke="black"
fill="transparent" />
<path
d="M 70 110 C 70 140, 110 140, 110 110"
stroke="black"
fill="transparent" />
<path
d="M 130 110 C 120 140, 180 140, 170 110"
stroke="black"
fill="transparent" />
</svg>
В примере выше создаются девять кубических кривых Безье. По мере продвижения вправо управляющие точки всё дальше отстоят друг от друга по горизонтали. По мере продвижения вниз они всё дальше отстоят от конечных точек. Важно отметить, что кривая начинается в направлении первой управляющей точки, а затем изгибается так, чтобы прийти к конечной точке в направлении второй управляющей точки.
Несколько кривых Безье можно соединить в цепочку, чтобы создать протяжённые плавные фигуры. Чтобы сохранить постоянный наклон, управляющая точка с одной стороны точки часто является отражением управляющей точки с другой стороны. В этом случае можно использовать сокращённую форму кубической кривой Безье — команду S (или s).
S x2 y2, x y (or) s dx2 dy2, dx dy
Команда S создаёт такой же тип кривой, как и раньше, но если ей предшествует другая команда S или команда C, первая управляющая точка считается отражением управляющей точки, использованной ранее. Если перед командой S нет другой команды S или C, текущая позиция курсора используется в качестве первой управляющей точки. Результат отличается от того, который дала бы команда Q с теми же параметрами, но похож на него.
Пример такого синтаксиса показан ниже. На рисунке слева заданные управляющие точки показаны красным, а выведенная управляющая точка — синим.
<svg width="190" height="160" xmlns="http://www.w3.org/2000/svg">
<path
d="M 10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"
stroke="black"
fill="transparent" />
</svg>
Другой тип кривой Безье — квадратичная кривая, обозначаемая Q, — на самом деле проще кубической. Для неё требуется одна управляющая точка, которая задаёт наклон кривой как в начальной, так и в конечной точке. Команда принимает два параметра: управляющую точку и конечную точку кривой.
Примечание: Изменения координат для q отсчитываются от предыдущей точки (то есть dx и dy задаются не относительно dx1 и dy1).
Q x1 y1, x y (or) q dx1 dy1, dx dy
<svg width="190" height="160" xmlns="http://www.w3.org/2000/svg"> <path d="M 10 80 Q 95 10 180 80" stroke="black" fill="transparent" /> </svg>
Как и для кубической кривой Безье, для объединения нескольких квадратичных кривых Безье в цепочку предусмотрена сокращённая команда T.
T x y (or) t dx dy
Эта сокращённая команда учитывает предыдущую управляющую точку и выводит на её основе новую. Это означает, что после первой управляющей точки можно создавать достаточно сложные фигуры, задавая только конечные точки.
Это работает, только если предыдущей командой была Q или команда T. В противном случае управляющая точка считается совпадающей с предыдущей точкой, и будут рисоваться только линии.
<svg width="190" height="160" xmlns="http://www.w3.org/2000/svg">
<path
d="M 10 80 Q 52.5 10, 95 80 T 180 80"
stroke="black"
fill="transparent" />
</svg>
Обе кривые дают похожие результаты, хотя кубическая кривая обеспечивает большую свободу в выборе её формы. Выбор кривой зависит от конкретной ситуации и от того, насколько симметрична линия.
Дуги
Ещё один тип кривой линии, которую можно создать с помощью SVG, — дуга, задаваемая командой A. Дуги представляют собой части окружностей или эллипсов.
Для заданных радиусов по осям x и y существуют два эллипса, которые могут соединить любые две точки (если они находятся в пределах радиуса окружности). На каждом из этих эллипсов можно выбрать два пути соединения точек, поэтому в любой ситуации доступны четыре возможные дуги.
Поэтому для создания дуги требуется довольно много параметров:
A rx ry x-axis-rotation large-arc-flag sweep-flag x y a rx ry x-axis-rotation large-arc-flag sweep-flag dx dy
В начале команда дуги принимает два параметра: радиусы по осям x и y. При необходимости см. описание элемента <ellipse> и его поведения. Последние два параметра задают координаты x и y конечной точки линии. Эти четыре значения вместе определяют основную структуру дуги.
Третий параметр задаёт поворот дуги. Лучше всего это объяснить на примере:
<svg width="320" height="320" xmlns="http://www.w3.org/2000/svg">
<path
d="M 10 315
L 110 215
A 30 50 0 0 1 162.55 162.45
L 172.55 152.45
A 30 50 -45 0 1 215.1 109.9
L 315 10"
stroke="black"
fill="green"
stroke-width="2"
fill-opacity="0.5" />
</svg>
В примере показан элемент <path>, проходящий по диагонали через страницу. В его центре вырезаны две дуги эллипсов (радиус по оси x = 30, радиус по оси y = 50). Для первой дуги поворот оси x оставлен равным 0, поэтому эллипс, по которому проходит дуга (показан серым), ориентирован вертикально. Для второй дуги поворот оси x установлен на -45 градусов. Это поворачивает эллипс так, что его малая ось совпадает с направлением контура, как показано на втором эллипсе в примере.
Для неповёрнутого эллипса на изображении выше доступны только две разные дуги, а не четыре, поскольку линия, соединяющая начальную и конечную точки дуги, проходит через центр эллипса. На немного изменённом примере можно увидеть два эллипса, образующие четыре разные дуги:
<svg xmlns="http://www.w3.org/2000/svg" width="320" height="320">
<path
d="M 10 315
L 110 215
A 36 60 0 0 1 150.71 170.29
L 172.55 152.45
A 30 50 -45 0 1 215.1 109.9
L 315 10"
stroke="black"
fill="green"
stroke-width="2"
fill-opacity="0.5" />
</svg>
Обратите внимание: каждый синий эллипс образован двумя дугами, в зависимости от направления движения — по часовой стрелке или против неё. У каждого эллипса есть короткая и длинная дуги. Два эллипса являются зеркальными отражениями друг друга. Они отражены относительно линии, соединяющей начальную и конечную точки.
Если расстояние между начальной и конечной точками больше того, которое могут охватить радиусы x и y эллипса, радиусы эллипса будут минимально увеличены, чтобы он мог достичь этих точек. Интерактивный пример CodePen внизу этой страницы хорошо это демонстрирует. Чтобы определить, достаточно ли велики радиусы эллипса или их нужно увеличить, необходимо решить систему уравнений, например эту в Wolfram Alpha. Это вычисление относится к неповёрнутому эллипсу с начальной и конечной точками (110, 215)→(150.71, 170.29). Решение (x, y) задаёт центр эллипса (или эллипсов). Решение будет мнимым, если радиусы эллипса слишком малы. Это второе вычисление относится к неповёрнутому эллипсу с начальной и конечной точками (110, 215)→(162.55, 162.45). Решение имеет небольшую мнимую составляющую, поскольку эллипс был увеличен совсем незначительно.
Четыре описанных выше пути задаются следующими двумя параметрами-флагами. Как упоминалось ранее, для контура можно выбрать один из двух эллипсов и один из двух путей на каждом из них — всего четыре возможных пути. Первый параметр — large-arc-flag. Он определяет, должна ли дуга быть больше или меньше 180 градусов; в конечном счёте этот флаг задаёт направление движения дуги по окружности. Второй параметр — sweep-flag. Он определяет, должна ли дуга начинаться под положительными или отрицательными углами, что по существу выбирает один из двух эллипсов. В примере ниже показаны все четыре возможные комбинации, а также два эллипса для каждого случая.
<svg width="360" height="360" xmlns="http://www.w3.org/2000/svg">
<path
d="M 100 100
A 45 45, 0, 0, 0, 145 145
L 145 100 Z"
fill="#00FF00A0"
stroke="black"
stroke-width="2" />
<path
d="M 250 100
A 45 45, 0, 1, 0, 295 145
L 295 100 Z"
fill="#FF0000A0"
stroke="black"
stroke-width="2" />
<path
d="M 100 250
A 45 45, 0, 0, 1, 145 295
L 145 250 Z"
fill="#FF00FFA0"
stroke="black"
stroke-width="2" />
<path
d="M 250 250
A 45 45, 0, 1, 1, 295 295
L 295 250 Z"
fill="#0000FFA0"
stroke="black"
stroke-width="2" />
<path
d="M 45 45 L 345 45 L 345 345 L 45 345 Z M 195 45 L 195 345 M 45 195 L 345 195"
fill="none"
stroke="black" />
<text x="140" y="20" font-size="20" fill="black">Large arc flag</text>
<text
x="-15"
y="195"
font-size="20"
fill="black"
transform="rotate(-90)"
transform-origin="20 195">
Sweep flag
</text>
<text x="120" y="40" font-size="20" fill="black">0</text>
<text x="270" y="40" font-size="20" fill="black">1</text>
<text x="30" y="120" font-size="20" fill="black">0</text>
<text x="30" y="270" font-size="20" fill="black">1</text>
</svg>
Дуги позволяют легко создавать части окружностей или эллипсов. Например, для круговой диаграммы потребуется отдельная дуга для каждого сектора.
При переходе к SVG с элемента <canvas> дуги могут оказаться самой сложной темой, но они также гораздо функциональнее. Единственные фигуры, которые сложно рисовать с помощью дуг SVG, — это полные окружности и эллипсы. Поскольку начальная и конечная точки любого контура, проходящего по окружности, совпадают, можно выбрать бесконечное количество окружностей, поэтому фактический путь не определён. Их можно приблизительно изобразить, немного сместив начальную и конечную точки контура, а затем соединив их другим сегментом контура. Например, можно создать окружность из двух дуг, каждая из которых представляет собой полуокружность. В таком случае часто проще использовать настоящий узел <circle> или <ellipse>. Эта интерактивная демонстрация поможет понять принципы работы дуг SVG.
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorials/SVG_from_scratch/Paths