Синтаксис SVG «path»: иллюстрированное руководство

Эта статья является вольным переводом статьи Криса Койера «The SVG `path` Syntax: An Illustrated Guide».

Элемент в SVG является основным способом рисования. С помощью него можно нарисовать всё что угодно! Я слышал, что на самом деле все другие элементы для рисования, в конечном счёте, используют path. Он имеет один атрибут для описания того, что рисуется: атрибут . Его значение — это мини-синтаксис и он выглядит довольно непонятно: это длинная строка с кучей цифр и букв. Я не эксперт, но решил поковыряться в нём.

Это пример кода средней сложности:

<path d="M213.1,6.7c-32.4-14.4-73.7,0-88.1,30.6C110.6,4.9,67.5-9.5,36.9,6.7C2.8,22.9-13.4,62.4,13.5,110.9
  C33.3,145.1,67.5,170.3,125,217c59.3-46.7,93.5-71.9,111.5-106.1C263.4,64.2,247.2,22.9,213.1,6.7z"/>

Мы можем слегка его причесать, для удобства понимания (это всё ещё валидный код):

<path d="
  M 213.1,6.7
  c -32.4-14.4-73.7,0-88.1,30.6
  C 110.6,4.9,67.5-9.5,36.9,6.7
  C 2.8,22.9-13.4,62.4,13.5,110.9
  C 33.3,145.1,67.5,170.3,125,217
  c 59.3-46.7,93.5-71.9,111.5-106.1
  C 263.4,64.2,247.2,22.9,213.1,6.7
  z" />

Буквы — это команды, а цифры — значения для этих команд. Запятые здесь необязательны, вместо них могут быть пробелы.

К примеру, первая команда, "M". Она говорит «перенеси перо на координаты 213.1,6.7». Ничего не рисуй, а просто перенести перо к этим координатам. Если теперь будет команда рисовать, то она начнёт именно с этих координат.

"M" — это одна из многих команд. По моим подсчётам, их около 18.

Многие (но не все) команды имеют пару: есть ПРОПИСНЫЕ и строчные версии команд. Прописная команда — абсолютная (absolute) версия, строчная — относительная (relative). Давайте разберём на примере команды "M":

  • M 100,100 означает «Перенеси перо на координаты 100,100».
  • m 100,100 означает «Перенеси перо на 100 пикселей вправо и на 100 пикселей вниз».

Давайте посмотрим на две абсолютные команды:

Теперь добавим относительную команду:

Как и команды "M" и "m", "L" и "l" принимают два типа значений: абсолютные и относительные. Есть ещё две пары команд, которые являются упрощёнными способами рисования линий. Вместо «l 25,0» мы могли бы использовать «h 25», что означает «нарисуй линию от текущей позиции на 25 пикселей вправо». Его старший брат, "H", как вы могли догадаться, означает нарисовать точную горизонтальную линию к координатам 25. Команды "V" и "v" делают то же самое, но по вертикали.

Посмотрите демонстрацию Chris Nager, в которой он умещает крест в небольшой кусочек кода, с помощью задания относительных координат.

See the Pen Hand drawn SVG rounded plus by Chris Nager (@chrisnager) on CodePen.

Видите последнюю команду, которую использовал Крис? «Z» (или «z», неважно) закрывает path. Эта команда, как и любая другая, необязательна. Это простой и быстрый способ вернуть перо туда, где оно находилось (возможно, эта позиция указана «M» или «m»).

Давайте посмотрим на команды, которые мы рассмотрели до этого:

M
x,y
Перейти к абсолютным координатам x,y
m
x,y
Подвинуть на x вправо и y вниз (или влево и вверх, если отрицательные значения)
L
x,y
Нарисовать линию к абсолютным координатам x,y
l
x,y
Нарисовать линию на x вправо и y вниз (или влево и вверх, если отрицательные значения)
H
x
Провести горизонтальную линию до координаты x
h
x
Провести горизонтальную линию на x вправо (или влево, если отрицательное значение)
V
y
Провести вертикальную линию до точки y
v
y
Провести вертикальную линию на y пикселей вниз (или вверх, если отрицательное значение)
Z
(или z)
Нарисовать линию до начала пути

Видите последнюю команду, которую использовал Крис? «Z» (или «z», неважно) закрывает path. Эта команда, как и любая другая, необязательна. Это простой и быстрый способ вернуть перо туда, где оно находилось (возможно, эта позиция указана «M» или «m»).

До сих пор мы рассматривали только прямые линии. "Path" — неплохой элемент с хорошим синтаксисом, хотя можно утверждать, что с помощью "polygon" можно нарисовать прямые проще, хоть и чуть ограничено.

Но суперсила path-а в кривых! И есть довольно много их типов.

Вспомните первый кусок кода, который мы рассматривали. В нём было много команд "C" и "c". Это Кривые Безье и им нужно больше значений, чтобы сделать что-то.

Команда "C" имеет три точки. Первые два значения определяют где находятся управляющие точки. Возможно, вам это знакомо по инструменту «Перо» в Adobe Illustrator.

Последняя точка обозначает место, где кривая заканчивается. Вот иллюстрация:

Строчная команда "c" работает так же, за исключением того, что координаты относительные.

Команда "S" (или "s") является родственной к "C", но она требует только два значения, так как считает, что первая точка кривой — это отражение последней, указанной в последней команде "S" или "C".

Команда "Q" одна из самых простых и она тоже требует только два значения. Первая точка, которую она требует, — это точка квадратичной кривой Безье. Это значит, что начальная и конечная точки кривой управляются из одной управляющей точки. Вторая точка — точка конца кривой.

Как и "S" дя "C", так и команда "T" является родственной к "Q". Как и в случае с командой "S", "T" считает управляющую точку отражением предыдущей. Поэтому вам нужно передавать в эту команду только одно значение — конечную точку.

Команда , наверное, самая сложная. По крайней мере, она требует самое большое количество значений. Вы передаёте ему значения ширины и высоты овала, информацию о том, как овал вращается. Плюс к этому, ещё информацию о том, как path будет двигаться по этому овалу. Информация с MDN:

Есть ещё два возможных эллипса для обхода пути и два разных возможных пути на обоих эллипсах, что даёт четыре возможных пути. Первый аргумент — large-arc-flag. Он определяет, должна ли дуга быть больше или меньше 180 градусов. В конечном счёте этот флаг определяет, в каком направлении дуга будет обходить данный круг. Второй аргумент — sweep-flag. Он определяет, должна дуга двигаться по отрицательным углам или по положительным, т.е. по сути определяет по какому из двух кругов она будет идти.

Схема Джони Тритхолла из его статьи про SVG неплохо объясняет это:

А теперь объяснения для каждой команды кривых в таблице:

C
cX1,cY1 cX2,cY2 eX,eY
Нарисовать кривую Безье на основе двух управляющих точек и конечной точки кривой
c То же самое, но с относительными координатами
S
cX2,cY2 eX,eY
То же, что и C, но первую управляющую точку указывать не нужно. Она считает, что эта точка является отражением последней точки, указанной в предыдущей команде или
s То же самое, но с относительными координатами
Q
cX,cY eX,eY
Рисует кривую на основе одной управляющей точки и заканчивает кривую в указанных координатах
q То же самое, но с относительными координатами
T
eX,eY
То же, что и , но первая управляющая точка автоматом берётся, как отражение последней точки у предыдущей команды или
t То же самое, но с относительными координатами
A
rX,rY rotation, arc, sweep, eX,eY
Рисует дугу, на основе кривой, созданной овалом. Определяет ширину, высоту и вращение овала. Вместе с конечной точкой, это даёт возможность для создания двух овалов. Так что, дуга и изгиб равны либо 0, либо 1 и они определяют какой будет овал и какая кривая, на его основе, будет нарисована
a То же самое, но с относительными координатами для eX,eY

Хотите увидеть кучу примеров? Вот они:

See the Pen Simple Path Examples by Chris Coyier (@chriscoyier) on CodePen.

Если вы смотрите на это через браузер на базе Blink, то вы можете увидеть анимацию, при наведении на элементы. Это говорит нам о том, что вы можете в CSS создавать пути. Например:

<svg viewBox="0 0 10 10">
  <path d="M2,5 C2,8 8,8 8,5" />
</svg>
svg:hover path {
  transition: d 0.2s;
  d: path("M2,5 C2,2 8,2 8,5");
}

Хотите знать больше об SVG? Я обещаю, что это будет реально круто. Я написал книгу об этом, которая называется «Practical SVG» и стоит не так дорого (а, вот оно чо!).

Василий:
Чтобы не выглядеть дегенератом, вначале надо приводить список команд, а потом примеры.