Подтвердить что ты не робот

Как я могу реализовать эффект смещенного пути в SVG без использования фильтров Javascript или расширения/эрозии?

У меня есть давний проект: базовый векторный графический инструмент, который работает в браузере и использует SVG и Javascript (возможно, вы видели кое-что из них в другом месте). Инструмент имеет только очень ограниченный набор функций, потому что аудитория ограничена, и цель очень конкретна, и на самом деле не разрешено быть другой функциональностью, чем то, что явно разрешено (вы знаете). Одна пропущенная функция - это размывание (также называемое вставкой или тонким) и расширяющие (выпуклые, утолщенные, полужирные) полигоны и другие графические элементы.

Я много раз использовал эффект смещения Adobe Illustrator, и с ним я могу легко создавать копии графических объектов, которые разбавлены или утолщены, не затрагивая оригинальный объект, поэтому он может быть почти любым, что поддерживается программой.

Я попытался использовать те же функции для работы в SVG, но без успеха.

Я пробовал следующее:
- расширять и стирать фильтры, но с неудовлетворительными результатами (см. изображение здесь)
- Библиотека Python Shapely на стороне сервера, но это обходное решение слишком медленное и позволяет вставлять или выделять только основные полигоны (описание здесь)
- найти javascript-библиотеку/код/​​функцию, которая может изменить данные пути для графических элементов, но ничего не найдено для javascript

Итак, существует ли какой-либо осмысленный способ реализовать это как эффект смещения пути и как?

4b9b3361

Ответ 1

Это "Ответьте на свой вопрос - поделиться своими знаниями, Q & A-style" -тильный ответ, но если у вас есть лучший ответ, пожалуйста, свободно используйте клавиатуру.

Я использовал SO только несколько дней, поэтому, пожалуйста, не уменьшайте меня до разрыва. У меня есть интересная обходная идея по этой проблеме, которая основана на масках и масках переменной ширины.

Но пусть начнется с вашей (или моей) первой идеи. Когда мы собираемся разрушать (тонкие) графические объекты в SVG, очевидная первая мысль заключается в использовании фильтра эрозии:

Но поскольку фильтр эрозии (и расширяется также) использует пиксельные данные (растрированный путь), результат не выглядит хорошо во всех случаях. На самом деле я никогда не видел красивого эрозии при использовании для фильтрации векторных объектов. Смотрите шляпу и рот:

Eroded image

У расширенного фильтра есть аналогичные проблемы (нос не очень приятный, а бейсболка - лоскутная и некоторые другие несоответствия):

Dilated image

Все пользователи Adobe Illustrator знают хорошие эффекты пути, которые могут использоваться для применения различных действий пути к фигурам (объектам). Эти эффекты не изменяют исходные данные пути, они создают только модифицированную копию объекта. Одним из наиболее используемых является Эффект смещения пути, который может использоваться для перехода с выбранного объекта на заданное расстояние (или что-то подобное), SVG: s фильтры эрозии и расширени имеют сходство с эффектом смещения Illustrator, но качество - как векторная операция (по сравнению с растровым).

Формат SVG в этом текущем состоянии, отсутствует поддержка смещенного на Illustrator смещения, но можно получить ту же функциональность, что и штрихи и маски с переменной шириной, как указано здесь.

Позвольте погрузиться в мир масок SVG. Расширение (или начальный путь или утолщение) можно достичь, просто увеличив ширину хода, но эрозия (или путь вставки или прореживание) нуждается в чем-то большем, например, маски. В SVG любой графический объект или элемент "g" можно использовать в качестве альфа-маски для компоновки текущего объекта в фоновом режиме (Рекомендация W3C SVG 1.1).

Вышеупомянутое означает, что в качестве маски можно использовать не только заполнение объекта, но и штрих. И, изменяя ширину хода пути, который используется в качестве маски, мы можем контролировать, какая часть текущего объекта (в который применяется маска с использованием атрибута маски) маскируется.. p >

Позвольте получить пример использования маски. Сначала мы определяем путь в SVG: s defs element:

<defs>
<path id="head_path" d="M133.833,139.777c1 ...clip... 139.777z"/>
</defs>

Когда мы определяем путь в элементе defs, он устраняет необходимость повторять одни и те же данные в других частях документа. Атрибут id пути используется для ссылки на путь из некоторой точки (ов) документа.

Теперь мы можем использовать данные этого пути в маске:

<defs>
...
<mask id="myMask" maskUnits="userSpaceOnUse">
<use xlink:href="#head_path" fill="#FFFFFF" stroke="#000000" 
stroke-width="18" stroke-linecap="round" stroke-linejoin="round"/>
</mask>
...
</defs>

Элемент 'use' ссылается на элемент 'path', идентификатор которого является 'head_path' и указывает, что в эту маску включен графический контент (в данном случае только данные пути) элемента 'head_path'. Ширина штриха, определенная на элементе "use" выше, будет значением эффекта смещения (erode). Эта сумма маскируется из элемента в случае, который мы собираемся сделать дальше.

Хорошо, пусть сначала нарисовать "голову" без маскировки, чтобы увидеть, насколько она красива:

...
</defs>
<use x="5" y="5" xlink:href="#head_path" fill="#4477FF" stroke="black"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>

Это создает следующую форму:

Original shape

Теперь проверьте, что мы можем добиться с помощью маски:

...
</defs>
<use x="5" y="5" xlink:href="#head_path" fill="#22EE22" stroke="black"
stroke-width="21" stroke-linecap="round" stroke-linejoin="round"
mask="url(#myMask)"/>

В приведенном выше элементе "use" указывается использование "myMask" в качестве маски и "head_path" в качестве графического содержимого. Эффект маски применяется к элементу "use" и рисуется следующая форма:

Masked shape

Если мы складываем оба над каждым, мы можем сравнить исходную голову с замаскированной головой:

Original and masked shape

Неплохо вообще? Давайте сравним первую попытку, используя SVG-версию с фильтром в маске:

Eroded vs masked

Левая часть фильтруется с эрозией, а правая - в масках, чтобы имитировать эффект смещения, подобный иллюстратору. Никаких странных артефактов в шляпе и рту!

Как насчет расширения? Есть ли способ устранить непоправимость пути на носу и лоскут бейсболки? Конечно. И метод действительно простой, но вроде взлома. К счастью, нет необходимости использовать маски. Вместо этого мы можем настроить ширину штриха для достижения желаемого эффекта. И поскольку удар уже используется для смелости, чтобы получить черный ход вокруг смелой формы (если когда угодно), мы должны добавить дополнительную копию элемента с небольшим более широким штрихом и выложить его ниже смелой формы:

<!-- To get the black stroke -->
<use x="220" y="5" xlink:href="#head_path" fill="red" stroke="black"
stroke-width="24" stroke-linecap="round" stroke-linejoin="round"/>
<!-- To get the boldened shape -->
<use x="220" y="5" xlink:href="#head_path" fill="red" stroke="red"
stroke-width="21" stroke-linecap="round" stroke-linejoin="round"/>

Это создает следующую форму:

Offset Path Effect applied

Здесь применяются как исходная форма, так и та, которая применяется в нашем обычном эффекте смещения:

Original and Offset Path Effect applied

Как наше обычное смещение сравнивается с расширенным фильтром:

Dilated vs Boldened

Левая (вверху) расширена с использованием SVG: s расширенный фильтр, правый - смелый, используя наш пользовательский эффект смещения. Довольно приятно, мне нравится. Путь точно следует исходному пути на данном расстоянии и никаких признаков лоскута на бейсболке.

И, наконец, давайте соединим все провода: Dilate/Origina/Erode vs Offset Path Combined

Левый (выше) использует фильтр растяжения/эрозии SVG, а правый использует эффект смещения с использованием Illustrator, который достигается с помощью маски SVG и более толстых штрихов. Какой из них вы выберете?

Заключение. Мы не вынуждены использовать Javascript или другие скрипты для сгущения или тонких графических элементов в SVG. Фильтры Erode и Dilate SVG могут иметь некоторые цели использования, но они не очень подходят для высококачественных "модификаций" пути. Маски немного сложны в использовании, но после нескольких экспериментов вы знакомы с ними. Я действительно надеюсь, что SVG в будущем будет поддерживать эффект смещенного пути изначально, без использования подобных хаков.

Я использовал шрифты, используемые в этих примерах, чтобы играть с фильтрами и масками: http://jsfiddle.net/7Y4am/
(Проверьте, по крайней мере, чтобы изменить ширину хода!)

(Извините, мой плохой английский, который заставил носителей языка смеяться до смерти, но, пожалуйста, помните, что я принадлежу к 94% человечества, который не говорит по-английски. Но, к счастью, у нас есть Google Translate.)