Относительные команды контуров SVG: текущая точка
Читайте абсолютные и относительные контуры SVG, отслеживая текущую точку. Проверьте пары moveto, сброс closepath и кубические координаты на собственном парном примере.
На этой странице
- Различайте положения и смещения
- Сравните два описания одной исходной иллюстрации
- Отслеживайте первую m и её неявные линии
- Отсчитывайте следующее перемещение от начала замкнутого подконтура
- Отсчитывайте каждую управляющую точку кубической кривой от одного начала
- Перемещайте иллюстрацию, не путая размещение с синтаксисом контура
- Проверяйте исходную геометрию перед изменением записи
- Частые вопросы
- Источники
Абсолютные команды контуров SVG, такие как M, L и C, задают положения в текущей пользовательской системе координат. Их относительные формы, m, l и c, задают смещения от текущей точки. Чтобы прочитать или переписать контур, отслеживайте эту точку после каждого сегмента. Если изменить букву команды, не изменив числа, форма может измениться.
Большую часть путаницы вызывают два правила: первая пара начальной команды m действует как абсолютное перемещение, а дополнительные пары — как относительные линии; Z или z замыкает подконтур и возвращает текущую точку к его началу. Новое относительное перемещение после замыкания отсчитывается от этой возвращённой точки.
Различайте положения и смещения
Спецификация контуров W3C определяет контур через текущую точку, подконтуры и команды рисования. Координаты выражены в пользовательских единицах SVG, которые не обязательно совпадают с экранными пикселями. viewBox или преобразование может сопоставить их другому положению на экране.
Если начать в (40, 40), эти две команды описывают одну и ту же линию:
L180 40
l140 0Первая задаёт конечную точку (180, 40). Вторая прибавляет (140, 0) к (40, 40). Обе заканчиваются в (180, 40) — эта точка становится текущей для следующего сегмента.
Напротив, l180 40 прибавляет (180, 40) и заканчивается в (220, 80). Синтаксис команды допустим, но она рисует другую линию.
| Команда | Значение координатных параметров |
|---|---|
| M x y | Начать подконтур в указанном положении |
| m dx dy | Начать подконтур относительно текущей точки с учётом описанного ниже поведения начальной m |
| L x y | Провести линию до указанного положения |
| l dx dy | Провести линию до текущей точки плюс смещение |
| C / c | Задать две управляющие точки и конечную точку как положения или смещения от одного начала |
| Z / z | Замкнуть подконтур к его началу и вернуть туда текущую точку |
Прописная и строчная Z действуют одинаково: у них нет координатных аргументов. Справочник MDN по d перечисляет команды и параметры каждой из них.
Сравните два описания одной исходной иллюстрации
Сохраните этот полный SVG как absolute.svg и откройте в браузере. Он содержит составной значок бирюзового цвета с квадратным отверстием и отдельную кубическую кривую кораллового цвета:
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="240" viewBox="0 0 300 240">
<path class="badge" fill="#173b40" fill-rule="evenodd" d="M40 40L180 40L210 80L180 140L40 140Z M80 70L80 110L120 110L120 70Z"/>
<path class="curve" fill="none" stroke="#f28567" stroke-width="6" d="M40 190C80 145 155 225 220 180"/>
</svg>Для relative.svg оставьте размер SVG, viewBox и стили, но замените два элемента path следующими:
<path class="badge" fill="#173b40" fill-rule="evenodd"
d="m40 40 140 0 30 40 -30 60 -140 0z m40 30 0 40 40 0 0 -40z"/>
<path class="curve" fill="none" stroke="#f28567" stroke-width="6"
d="m40 190c40 -45 115 35 180 -10"/>Мы отобразили оба исходных файла в браузере вместе с намеренно испорченной копией абсолютного значка. В испорченной копии только первая команда L180 40 заменена на l180 40; числа остались прежними.

Наша страница использовала встроенные SVG-методы getTotalLength() и getPointAtLength() для сравнения 301 точки каждого контура на соответствующих долях полной длины. Отображаемые длины составили 657.082 пользовательских единицы для каждого значка и 189.066 для каждой кривой. Максимальное различие между выборочными точками отображалось как 0.000000 для обеих пар.
Это измерение подтверждает совпадение именно этих строк: вершины линий и точки кубической кривой также совпадают при вычислениях ниже. Оно не доказывает, что произвольное переписывание или конвертер обрабатывает все команды SVG. Во всём сравнении используются одинаковая область просмотра без преобразований и одинаковые настройки оформления.
Отслеживайте первую m и её неявные линии
Наш значок начинается так:
m40 40 140 0 30 40 -30 60 -140 0zТолько первая пара выполняет перемещение. Остальные пары ведут себя как неявные относительные сегменты l. Определение moveto явно оставляет эти последующие пары относительными, хотя начальная m40 40 считается абсолютным началом.
Отслеживайте пары по очереди:
| Пара или команда | Операция | Текущая точка после неё |
|---|---|---|
| m40 40 | Начальное перемещение | (40, 40) |
| 140 0 | Неявная относительная линия | (180, 40) |
| 30 40 | Неявная относительная линия | (210, 80) |
| -30 60 | Неявная относительная линия | (180, 140) |
| -140 0 | Неявная относительная линия | (40, 140) |
| z | Замыкание к началу этого подконтура | (40, 40) |
Для сравнения: прописная M с несколькими парами превратила бы последующие пары в неявные абсолютные сегменты L. Она не трактовала бы каждую пару как новое перемещение и не использовала бы те же смещения, что этот пример со строчной командой.
Элемент path задаёт собственную последовательность контура. Не отсчитывайте его начальную относительную m от конечной точки другого, не связанного с ним элемента path.
Отсчитывайте следующее перемещение от начала замкнутого подконтура
Отверстие начинается после первой z:
m40 30 0 40 40 0 0 -40zВ этот момент текущая точка — (40, 40), поэтому новое относительное перемещение прибавляет (40, 30) и начинает отверстие в (80, 70). Далее неявные линии достигают (80, 110), (120, 110) и (120, 70) перед замыканием.
Если ошибочно взять за основу конечную точку последней линии внешнего значка (40, 140), перемещение привело бы к (80, 170). Именно предыдущее замыкание делает такой расчёт неверным. Определение closepath возвращает текущую точку к начальной точке текущего подконтура.
Оба подконтура принадлежат одному элементу path. Его fill-rule="evenodd" превращает внутренний квадрат в отверстие в этом тестовом образце. При сравнении переписанных координат сохраняйте правило заливки и оформление, чтобы изменение заливки не скрывало проверяемую геометрию.
Отсчитывайте каждую управляющую точку кубической кривой от одного начала
Отдельная кривая начинается в (40, 190):
M40 190 C80 145 155 225 220 180
m40 190 c40 -45 115 35 180 -10Для этого одного сегмента со строчной c все три пары — смещения от (40, 190). Вторая управляющая точка не отсчитывается от первой, а конечная — от второй.
| Точка | Относительная пара | Абсолютное положение |
|---|---|---|
| Первая управляющая | (40, -45) | (80, 145) |
| Вторая управляющая | (115, 35) | (155, 225) |
| Конечная | (180, -10) | (220, 180) |
После сегмента обновите текущую точку до его конечной точки (220, 180). Следующий относительный сегмент использовал бы это новое начало. Урок MDN о контурах объясняет кубические управляющие точки и абсолютные/относительные формы; руководство по стыкам кривых Безье отдельно разбирает касательные направляющие и сокращённую команду S.
Не применяйте вычитание координат ко всем числам во всех командах. У дуги радиусы, поворот и флаги выполняют другие задачи; между абсолютным и относительным положением переключается только пара координат конечной точки. Прежде чем переписывать данные A или a, прочитайте объяснение флагов дуг. Этот пример показывает линии, перемещения, замыкание и один обычный кубический сегмент, а не универсальную процедуру преобразования контуров.
Перемещайте иллюстрацию, не путая размещение с синтаксисом контура
В этом полностью относительном составном значке замена начальной m40 40 на m60 60 сдвигает вершины на (20, 20): последующие смещения и относительное перемещение подконтура следуют за изменённым началом. Отдельный контур кривой остаётся без изменений. В смешанных данных последующие абсолютные положения также остаются привязаны к указанным координатам, поэтому изменение первого перемещения может деформировать контур.
Чтобы переместить всю иллюстрацию из двух контуров как единое целое, сохраните обе строки d и поместите их элементы в группу с transform="translate(20 20)". Спецификация систем координат SVG объясняет, как преобразования задают отображение координат. Преобразование группы меняет размещение, не переписывая исходные данные контуров.
Проверьте, что область просмотра по-прежнему вмещает перемещённую иллюстрацию: перенос группы не увеличивает её холст автоматически. Руководство по порядку преобразований SVG объясняет размещение при сочетании переноса и масштабирования.
Проверяйте исходную геометрию перед изменением записи
PerfectVector может помочь, если иллюстрация существует только в PNG или JPG. Подготовьте вариант SVG, а затем сравните восстановленные силуэт, отверстия и форму кривых с исходником, прежде чем редактировать данные контуров. Абсолютная или относительная запись сама по себе не определяет пригодность восстановленной геометрии.
Используйте готовый векторный оригинал напрямую или перерисуйте простой символ, если так проще контролировать результат. Переписывание команд не восстанавливает задуманную форму из отсутствующей растровой информации. Обзор векторизации изображений объясняет этот отдельный этап реконструкции.
Редактируя пригодный SVG, сохраните копию оригинала, меняйте по одному поддерживаемому сегменту и сравнивайте реальный файл в одинаковом масштабе. Отслеживайте и начало подконтура, и текущую точку. Сохраняйте настройки заливки и обводки во время сравнения, затем проверяйте экспортированный файл в приложении, где он будет использоваться.
Частые вопросы
Начальная строчная m отсчитывается относительно другого контура? Нет. Когда m — первая команда контура, её первая пара считается абсолютным началом. Дополнительные пары — неявные относительные линии, а конечная точка другого элемента path не служит началом отсчёта.
Где находится текущая точка после Z или z? В начале только что замкнутого подконтура. Следующее относительное перемещение отсчитывается от этой возвращённой точки, а не от конца предыдущей линии.
Можно ли преобразовать контур, переведя команды в нижний регистр? Нет. Координатные значения нужно пересчитать в соответствии с семантикой каждой команды. В этом примере L180 40 превращается в l140 0 от текущей точки (40, 40), а l180 40 рисует другую линию.
Источники
- W3C — SVG 2 Paths — Определяет текущие точки, начальное moveto, неявные линии, замыкание и кубические параметры.
- MDN — Paths tutorial — Иллюстрирует абсолютные и относительные команды линий и кривых.
- MDN — d attribute — Перечисляет назначение параметров команд, включая дуги и closepath.
- W3C — SVG 2 Coordinate Systems — Объясняет отображение пользовательских координат и размещение иллюстраций с помощью преобразований.
Начинаете с иллюстрации, которая есть только в растре? Подготовьте контуры SVG с PerfectVector, проверьте восстановленные силуэт и отверстия, затем редактируйте только понятные вам команды и сверяйте итоговый SVG с оригиналом.
Ещё из блога

SVG-изображения Graphviz: переносимая графика узлов
Добавьте SVG-графику в узел Graphviz, проверьте ссылку на изображение и сравните полный комплект ресурсов, перенесенную диаграмму и автономную копию для передачи.

SVG в Matplotlib: график и логотип в виде контуров
Экспортируйте график Matplotlib в SVG, добавьте отдельные контуры логотипа через svgutils и проверьте итоговый файл на встроенные пиксели, размещение и изменения шрифтов.