- Странности обводки в SVG
- SVG: заливка и обводка
- fill-rule
- fill-opacity
- stroke
- stroke-width
- stroke-linecap
- stroke-linejoin
- stroke-dasharray
- stroke-dashoffset
- stroke-opacity
- Почему SVG stroke-dashoffset не работает?
- 2 ответа 2
- Решение с помощью Handwriting
- SVG Почему не срабатывает CSS анимация stroke-dashoffset
- 3 ответа 3
- Вариант с одиночным контуром линий.
- Smil Animation VS CSS animation
- Can you control how an SVG’s stroke-width is drawn?
- 11 Answers 11
Странности обводки в SVG
Экспериментируя с SVG можно обнаружить много странных моментов. Получить странное при манипуляциях с масштабированием ещё как-то ожидаемо, но внезапно сюрпризы преподнесло свойство stroke-width .
stroke-width задает тощину обводки для фигуры. Если в HTML рамка отрисовывается от внешнего края внутрь фигуры и увеличивает её размеры (что можно исправить с помощью box-sizing ), то в SVG обводка ведет себя иначе: во-первых, она не растягивает фигуру, во-вторых она отрисовывается и внутрь, и наружу относительно внешнего края фигуры.
Чтобы увидеть как это работает, возьмем пару простых фигур:
Круг с диаметром 60px, квадрат — 60х60px.
С помощью CSS добавим фигурам рамку:
Рамка зеленого цвета, толщиной 30 пикселей. Чтобы видеть как она накладывается на фигуру, рамке задана полупрозрачность ( stroke-opacity: .5 ).
Очевидно, что рамка отрисовывается от внешнего края фигуры в обоих направлениях: и внутрь, и наружу.
Обычная рамка ведет себя довольно понятно и предсказуемо, но самое интересное начинается, если задать рамку, превышающую ширину фигуры больше чем в два раза. Чем больше разница — тем интересней результат. Чтобы было хорошо видно, я задала рамку равную трехкратному значению ширины (60 * 3 = 180):
У квадрата с рамкой всё в порядке, а вот с кружком происходит нечто странное: если толщина обводки больше чем в два-три раза превышает ширину фигуры, между кружком и рамкой образуются белые поля, а толщина рамки уменьшается.
Чем больше разница между значениями, тем больше белые поля и тем тоньше рамка (радиус 10, толщина обводки — 200):
Совсем не то, что хотелось бы получить.
Ещё более интересный результат получается, если добавить свойство stroke-dasharray .
Выглядит так, как будто рамка доходит до середины фигуры и продолжает отрисовываться оттуда.
Всё это как бы намекает нам, что толщина рамки не должна быть больше двухкратного значения ширины или диаметра фигуры, хотя можно поступить и наоборот: задавать очень большие значения и получать интересные варианты лучей.
Думаю, редко кому придет в голову задавать обводке запредельные значения ширины, но я обнаружила эту странность в поведении, когда хотела сделать именно это: взять маленький кружок и задать ему большую рамку, чтобы увеличить таким образом его размер.
Зачем это может быть нужно?
Предположим, есть круглая маска и картинка под ней:
Я хочу анимировать маску, чтобы она пропорционально растягивалась и сужалась относительно центра картинки. Первым делом в голову, конечно, приходит transform . Код анимации:
Так как центр трансформаций в SVG находится в левом верхнем углу области отрисовки, фигура движется совсем не так, как хотелось бы. Задаем центр трансформаций, который нужен нам:
В Chrome анимация будет работать как задумано: маска увеличивается от центра и затем уменьшается в обратном направлении. В Firefox она не будет работать вообще: Firefox не анимирует трансформации внутри масок.
Способ с трансформацией не работает. Какие ещё варианты есть? Вот как раз в этом случае можно попробовать анимировать толщину обводки.
Почему это сработает?
Небольшое лирическое отступление: в отличие от clipPath , который обрезает фигуру по векторному контуру, игнорируя заливки и обводки контура, в работе маски принимает участие всё её графическое содержимое.
Для примера возьмем кружок c обводкой и используем его в mask и clipPath :
Для фигур внутри clipPath можно было бы попробовать анимировать transform , но они тоже не анимируются в Firefox. Таким образом, в нашем распоряжении остаются только маски и манипуляции с обводками. Конец лирического отступления.
Используя обводки, пробую повторить поведение маски, пропорционально увеличивающейся относительно центра. Для этих целей я беру маску с маленьким кружком внутри:
Задаю ей белую заливку и добавляю обводку:
Добавляю анимацию толщины обводки:
Весь итоговый код:
В отличие от способа с transform , обводка замечательно анимируется в Firefox, и это можно было бы использовать, если бы не ограничение на толщину обводки, описанное выше.
Таким образом, с одной стороны, задавать толстую рамку для маленького элемента кажется странной идеей, с другой — это можно было бы использовать в практических целях, так что жаль, что stroke-width отрисовывается не так как хотелось бы.
Некоторой пикантности добавляет тот факт, что как раз в Firefox анимация обводки в маске дает именно желаемый результат: маска увеличивается от центра к краям без каких-либо зазоров между фигурой и обводкой — фигура получается цельная.
Ещё интереснее ведет себя Safari: в нем фигура маски цельная, а результат применения маски к картинке — с зазорами.
Таким образом, при желании получить анимированую маску, можно сочетать анимацию transform для Хрома (и других webkittens) с анимацией stroke-width для Firefox, например: так:
Способ странный, но это работает.
Правда, обе анимации не будут работать в IE, потому что он вообще не поддерживает анимации в SVG.
Анимируя stroke-width в маске можно делать разные другие интересные штуки, но это уже тема для отдельного поста.
Версии браузеров на момент написания поста: Chrome 36, Firefox 31, Safari 7, Opera 23, IE 11.
Источник
SVG: заливка и обводка
В SVG заливка и обводка имеют много разных интересных опций, которые предоставляют возможности гораздо шире того, что есть в CSS.
Например, можно нарисовать SVG-паттерн и использовать его не только в заливке, но и в обводке. Заливке и обводке можно указывать разную прозрачность, также можно управлять пунктирной обводкой, на чем можно построить интересные анимированные эффекты.
В качестве заливки и обводки можно задавать none , цвета, ключевые слова ( currentColor и transparent ), а также градиенты и паттерны.
Возможные значения: none , ключевые слова, цвета, паттерны и градиенты. Значение по умолчанию — black .
fill-rule
Свойство определяет как будут заливаться сложные фигуры, имеющие пересечения внутри себя. Для простых фигур ни на что не влияет.
Возможные значения: nonzero , evenodd
fill-rule=»nonzero» интересно ведет себя для фигур из двух путей. Например, если внешний круг нарисован по часовой стрелке, а внутренний в обратном направлении, центральный круг останется без заливки (слева). Если же оба круга нарисованы в одном направлении — фигура зальется полностью (справа):
fill-opacity
Управление прозрачностью заливки. Можно задавать значения от 0.0 до 1.0 или в процентах. Правда, Firefox не любит значения в процентах для градиентов (пруфлинк, смотреть в FF).
stroke
Цвет обводки. Значения по умолчанию нет.
stroke-width
Толщина обводки, можно задавать в единицах длины или в процентах. Значение по умолчанию: 1.
stroke-linecap
Свойство определяет как будут выглядеть концы линий. Возможные значения: butt , round , square . Значение по умолчанию: butt .
stroke-linejoin
Определяет как будут выглядеть соединения линий на углах. Возможные значения: miter , round , bevel . Значение по умолчанию: miter .
stroke-dasharray
Управляет видом пунктирной обводки. Можно задавать в единицах длины или в процентах. Если задано одно значение, второе значение считается равным первому. Например, stroke-dasharray=»1″ нарисует линию из отрезков длиной одну единицу разделенных пробелами такой же ширины.
Примеры разных пунктирных линий:
Используя обводку и простые фигуры можно получить удивительные вещи:
Также stroke-dasharray интересно сочетается с анимацией:
stroke-dashoffset
Свойство позволяет задать смещение пунктирной обводки относительно первоначального положения. Значение задается в единицах длины или в процентах, значения могут быть отрицательными. Значение по умолчанию: 0.
В этом примере оранжевые и желтые линии смещены относительно красной с помощью разных значений stroke-dashoffset :
Сочетая stroke-dashoffset и stroke-dasharray можно получить интересные эффекты.
Для полноценного просмотра воспользуйтесь браузерами на Webkit. Ссылка на полную версию.
Для перезапуска нажмите Rerun.
Несколько вдохновляющих ссылок про анимацию на stroke-dashoffset :
stroke-opacity
Прозрачность обводки. Задаются значения от 0.0 до 1.0.
Анимация обводки позволяет получить совершенно удивительные вещи. Правда, я в своих примерах использовала CSS (и это демо не играет в Firefox) и SVG-анимацию, которая работает таки везде, но задается странно, длинно и неудобно. Думаю, что оптимальнее всего для анимации SVG использовать JavaScript-библиотеки.
Источник
Почему SVG stroke-dashoffset не работает?
У меня возникла проблема с получением пути моего SVG для анимации с использованием stroke-dasharray в сочетании с stroke-dashoffset . Длина пути рассчитывалась с помощью Js .
Ниже я включил JsFiddle , точно показывающий, чего я пытаюсь достичь.
Я искал и во многих примерах, с которыми я сталкивался, и из которых пытался взять решения, не работали для меня. На этом этапе я прихожу к выводу, что я чего-то упускаю, и пытаюсь понять, почему это не работает.
2 ответа 2
Решение с помощью Handwriting
Когда фигура SVG имеет двойной контур с разным расстоянием между контурами и формой в точках изменения направления, то для анимации рисования контуров лучше применить технику — Handwriting
Суть её заключается в анимации средней линии, которая имеет достаточную ширину, чтобы перекрыть самые широкие места исходной фигуры.
Эту среднюю линию необходимо нарисовать в векторном редакторе и сохранить её path
Далее этот path анимируем с помощью рисования линии от нуля до максимума. Добавляем этот элемент в маску и применяем маску к исходной фигуре контура облака. Длина анимированной маски изменяется, открывая тем самым исходный контур облака.
Создавая иллюзию рисования линии с разной шириной и формой.
Вариант с повторной анимацией после двухсекундной паузы
Источник
SVG Почему не срабатывает CSS анимация stroke-dashoffset
Подскажите почему не срабатывает анимация «растущей линии» stroke-dashoffset ?
3 ответа 3
Вариант с одиночным контуром линий.
Ниже показан старый вариант иконки с двойными контурами. Зелёный цвет.
Красный цвет — одинарный контур, нарисованный с помощью инструмента — Рисовать кривые Безье и прямые линии На рисунке — синяя стрелка
В результате изменилась длина линий для анимации:
Для круга было 158 стало 78
Для галочки: было 72 стало 33
Не указан был цвет строки, без этого строку и её анимацию не видно. stroke:#07B53B;
Еще нужно установить fill:none; Так как анимируется строка, а не заливка.
Элементы SVG нарисованы двойными контурами, если так нужно, то можно оставить.
Но лучше, на мой взгляд перерисовать фигуры одиночным контуром, тогда анимация будет другой.
Smil Animation VS CSS animation
Этот ответ дан, чтобы не сваливать всё в одну кучу и иметь возможность сравнить в учебных целях анимации CSS и SMIL.
Названия классов, id сохранены, чтобы легче было сравнивать реализацию одинаковых моментов.
1#. Вариант анимации stroke-dashoffset
Как и в в ответе с вариантами анимации CSS stroke-dashoffset (отступ линии) уменьшается от максимального значения до нуля values=»78;0″ реализуя тем самым рисование линии от нуля до максимума
2#. Вариант анимации stroke-dasharray
Здесь эффект рисования заключается в изменении длины пробелов и черточек
Сначала длина черты равна нулю, а пробел максимален (78), поэтому линия не видна
stroke-dasharray=»0,78″
Затем черта становится максимальной, а пробел равен нулю
stroke-dasharray=»78,0″
Итоговая формула анимации:
3#. Вариант анимации stroke-dasharray из средней точки
Эта техника основана на свойстве stroke-dasharray в наличии нескольких пар атрибутов черточек и пробелов.
Если нужно рисовать симметрично двумя линиями из одной точки, то используются две пары атрибутов.
stroke-dasharray: 0,39 0,39; Сумма черточек равна нулю, пробелов равна 78. Поэтому линия будет не видна.
В сумме все длины пробелов и черточек при любой комбинации, должны быть равны максимальной длине линии, которая вычисляется методом JS getTotalLength()
4#. Вариант анимации из средней точки, которая сдвинута stroke-dashoffset
Начало анимации из средней точки можно сдвинуть в любую сторону. Это зависит только ль значения параметра stroke-dashoffset
При длине 78px линии, stroke-dashoffset=»39″ сдвигает начало анимации на половину линии.
Источник
Can you control how an SVG’s stroke-width is drawn?
Currently building a browser-based SVG application. Within this app, various shapes can be styled and positioned by the user, including rectangles.
When I apply a stroke-width to an SVG rect element of say 1px , the stroke is applied to the rect ’s offset and inset in different ways by different browsers. This is proving to be troublesome, especially when I try to calculate the outer width and visual position of a rectangle and position it next to other elements.
- Firefox adds 1px inset (bottom and left), and 1px offset (top and right)
- Chrome adds 1px inset (top and left), and 1px offset (bottom and right)
My only solution so far would be to draw the actual borders myself (probably with the path tool) and position the borders behind the stroked element. But this solution is an unpleasant workaround, and I’d prefer not to go down this road if possible.
So my question is, can you control how an SVG’s stroke-width is drawn on elements?
11 Answers 11
No, you cannot specify whether the stroke is drawn inside or outside an element. I made a proposal to the SVG working group for this functionality in 2003, but it received no support (or discussion).
As I noted in the proposal,
- you can achieve the same visual result as «inside» by doubling your stroke width and then using a clipping path to clip the object to itself, and
- you can achieve the same visual result as ‘outside’ by doubling the stroke width and then overlaying a no-stroke copy of the object on top of itself.
Edit: This answer may be wrong in the future. It should be possible to achieve these results using SVG Vector Effects, by combining veStrokePath with veIntersect (for ‘inside’) or with veExclude (for ‘outside). However, Vector Effects are still a working draft module with no implementations that I can yet find.
Edit 2: The SVG 2 draft specification includes a stroke-alignment property (with center|inside|outside possible values). This property may make it into UAs eventually.
Edit 3: Amusingly and dissapointingly, the SVG working group has removed stroke-alignment from SVG 2. You can see some of the concerns described after the prose here.
Источник