Как поменять fill у svg через css
Перейти к содержимому

Как поменять fill у svg через css

  • автор:

До­ступ­ные SVG-икон­ки с ин­лай­но­вы­ми спрай­та­ми

Если вы ищете повод использовать иконки в проекте, то далеко ходить не надо. Как хорошо заметил Оливер Рейхенштейн в своём докладе «Об иконках» на Smashing Conf во Фрайбурге: «На определённом этапе проекта кто-нибудь обязательно приходит и говорит: нам нужны иконки!». Так зачем они нужны людям?

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

Вне зависимости от аргументации, нам нужно быть уверенными в том, что люди, которые не могут видеть или распознать иконки, понимают их назначение.

Иконка с рукой, которая нажимает на кнопку. Рядом с ней иконка с руками, держащими три красных волнистых линии, которые напоминают бекон.

Сами по себе иконки могут неправильно интерпретироваться, что продемонстрировала Мэлори ван Ахтерберг во время своего доклада на Fronteers в 2017. Их самая главная проблема — отсутствие текста. Текст — самый доступный вид информации в вебе. Скринридеры понимают его лучше всего. Это относится к большинству вспомогательных технологий, например, к приложениям для переводов и брайлевским дисплеям. Поэтому, если на нашей странице есть нетекстовая информация, например, иконки, мы должны добавить текст, который дублирует для пользователей её значение. Иначе мы можем сделать наши интерфейсы сложными для понимания.

Что вы сделаете в первую очередь, если увидите, что кто-то тонет? Вызывайте 911.

Как использовать SVG-графику для иконок Скопировать ссылку

SVG или масштабируемая векторная графика (Scalable Vector Graphic) — это часть спецификации расширяемого языка разметки (Extensible Markup Languag, XML), которая может быть встроена в HTML-документ при помощи элемента , как в примере кода ниже (в нём SVG — стрелка в браузере, указывающая вниз):

В этом простом примере есть всё, что нужно для отображения SVG в браузерах, которые её поддерживают. Однако, без указания высоты и ширины, SVG будет отображаться настолько большой, насколько это позволит доступная область просмотра. В примере ниже показано как это исправить:

Одиночный вспомогательный CSS-класс, присвоенный нашим SVG-иконкам, задаёт им нужное поведение. Затем он переопределяет эти значения и отлично масштабирует иконки в соответствии с размером текста.

.svg-icon < /* Разместить иконку выше базового текста. */ position: relative; top: 0.125em; /* Не дать иконке сжаться внутри flex-контейнера. */ flex-shrink: 0; /* * Масштабировать иконку до размера шрифта родительского * элемента. */ height: 1em; width: 1em; /* Установить для иконки любой цвет, который задан родителю. */ fill: currentColor; /* * Если иконка используется в ссылке, для которой задан цветовой * переход, мы можем также задать для fill нужное значение * transition. */ transition: fill 0.3s; >

Ниже пример HTML-кода:

Я сделал демо на CodePen, чтобы показать, на что способен этот одиночный CSS-селектор. Мы можем увеличить или уменьшить значение font-size для параграфа в инспекторе CSS и увидеть, как иконка увеличивается вместе с текстом. Мы также можем изменить значение color и посмотреть, как это повлияет на неё. При наведении курсора на ссылку или при фокусе на ней одновременно изменяется как цвет ссылки, так и цвет заливки иконки.

Решая эту проблему, мы сталкиваемся с другой: нам не хватает текстового эквивалента для графики, которую мы добавили на нашу страницу.

Делаем SVG-иконку доступной Скопировать ссылку

Давайте предположим, что нам нужно создать кнопку, которая переключает видимость навигации по сайту. При первом нажатии на неё навигация будет показана, а при повторном снова скрыта. Надеюсь, что все согласны, что кнопка — это кнопка, и поэтому она должна быть . В нашем случае дизайн-макета недостаточно. Всё, что дал нам дизайнер — это иконка гамбургера, без текста. Переключаемся на редактор: добавляем в кнопку SVG.

Теперь нужно добавить немного текста, с которым могли бы взаимодействовать вспомогательные технологии. Используя инлайновый SVG, мы можем добавить элемент для первого дочернего элемента и присвоить ему ID. Затем нам нужно сослаться на нужное значение ID с помощью атрибута aria-labelledby , который задан открывающему тегу :

  

Теперь, когда кто-то установит фокус на кнопке, будет объявлен текст заголовка (некоторые браузеры даже показывают текст внутри в виде всплывающей подсказки). Обратите внимание на сочетание атрибута и значения focusable=»false» в SVG! Это помешает установить фокус на SVG в Internet Explorer и Microsoft Edge. Это баг, который не исправлен для 10 и 11 версий Internet Explorer.

У нас есть варианты Скопировать ссылку

Есть другой способ добавить скрытый текст рядом с иконкой. Для него HTML и вспомогательный CSS-класс нужны чуть меньше, и он работает так же как в примере выше.

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

  

Вспомогательный CSS-класс выглядит так:

.visually-hidden < /* Убрать текст из потока */ position: absolute; /* Уменьшить его высоту и ширину до одного пикселя */ height: 1px; width: 1px; /* Скрыть выходящие за пределы контейнера элементы или текст */ overflow: hidden; /* Установить для clip нулевое значение */ clip: rect(0, 0, 0, 0); /* Текст не будет перенесён на вторую строку */ white-space: nowrap; >

Не сильно отличающийся пример Скопировать ссылку

И вот наши дизайнеры решили добавить другую кнопку с текстом и иконкой рядом с ним. Если у вас есть текст рядом с иконкой, то не добавляйте заголовок и описание, а замените role=»img» у SVG на aria-hidden=»true» . Добавление к элементу атрибута aria-hidden=»true» полностью удаляет его и его дочерние элементы из дерева доступности. Такой элемент не будет доступен для Accessibility API:

  

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

Вот демо, которое демонстрирует все четыре варианта кнопки: создание кнопки с доступной SVG-иконкой.

Установив фокус на кнопке, скринридер объявит: «Меню, кнопка». Прекрасно. Однако теперь, визуально, мы получили тот же SVG, но с другим кодом. Представьте, что вам нужно добавить иконки в другом контексте, в котором подписи из первого варианта не используются. А потом ещё в одном. И ещё. Этот вариант не идеален.

Нам нужно быть осторожными, и не задать aria-hidden=»true» для элемента с role=»none» ! У них разные сценарии использования и конечные результаты. Скотт Охара написал замечательную статью о том, когда и какой из атрибутов использовать.

Пишите меньше кода — используйте спрайт Скопировать ссылку

Процитирую слова Хейдона Пикеринга из его доклада «Пишите меньше чёртового кода» с Beyond Tellerrand Berlin 2016: «Чем меньше кода, тем код лучше! Меньше кода, над которым нужно думать. Меньше кода поддерживать. Меньше данных передавать по сети».

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

Разместив пустой в качестве первого потомка открывающего тега и скрыв его от всех (зрячих или нет) при помощи инлайнового display: none , мы создали пространство для вставки наших иконок. Важно именно инлайново задать display: none , потому что мы не хотим, чтобы спрайт был видим при загрузке наших таблиц стилей браузером! Если у вас есть критические стили для сайта, вы можете добавить свойство туда, и не трогать спрайт.

Примечание: это только один из множества вариантов создания SVG-спрайта! Есть несколько способов сделать это, но в этой статье невозможно объяснить их все. Сара Суайдан очень подробно рассказывает о различных вариантах создания SVG-спрайта со всеми преимуществами и проблемами, которые имеются в каждом из подходов.

При использовании SVG-спрайта для системы иконок можете не трогать SVG. Поскольку вы собираетесь использовать одну иконку в элементе , вам понадобится подписать её или вообще скрыть, если она декоративная.

В общем, всегда следует оптимизировать SVG-код независимо от сценария использования. К счастью для нас, поскольку это интернет и в нём есть миллион инструментов, созданных миллионами людей, нам не нужно самим выполнять эту тяжёлую работу.

SVGO(MG) Скопировать ссылку

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

Для тех, кто предпочитает командную строку графическому интерфейсу, есть svgo. Мы можем добавить массу параметров для оптимизации SVG: что удалить, что оставить и даже что оставить принудительно. Для тех, кто предпочитает таск-менеджеры, есть grunt-svgmin и точно такой же gulp-svgmin, в которых используется SVGO. Сара Суайдан сделала отличный обзор существующих инструментов с их преимуществами и недостатками.

Если вам больше нравятся инструменты с графическим интерфейсом, есть SVGOMG, который сделал Джейк Арчибальд. Он такой же мощный как вариант с командной строкой и сразу показывает результат (код и изображение). Вместо того, чтобы писать параметры в нашем терминале, мы можем на правой панели выбрать нужную опцию или убрать её. Единственная оговорка: может быть довольно утомительно загружать и оптимизировать каждую иконку по отдельности.

Создание спрайта Скопировать ссылку

До использования SVGOMG наши иконки могут выглядеть как в примере ниже. Это зависит от того, какими программами для создания графики вы пользуетесь (в примере показан SVG-код, который был создан в Adobe Illustrator при выборе параметра «Сохранить как»):

Примечание: если выбрать в Adobe Illustrator параметр «Экспорт», то получится более чистый SVG-код!

Открывая SVG в браузере, мы видим угол 90 градусов, направленный вниз. Пропустив этот код через SVGOMG со всеми выбранными чекбоксами, мы получим хороший минифицированный SVG-файл.

Примечание: единственная опция, которую не надо выбирать — это «Remove ViewBox»! Нам часто требуется сохранить для иконок атрибут viewBox, чтобы они правильно отображались!

Посмотрим, что осталось после оптимизации:

После добавления SVG-кода в спрайт, нам только осталось слегка его изменить (я добавил переносы строк для того, чтобы код стал более читаемым):

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

   Перейти к следующему разделу.    

Прокрутите вниз для получения дополнительной информации!

С помощью одиночного тега мы можем ссылаться на ID этого SVG в спрайте. В примере выше у нас есть четыре разных сценария использования, все с одной и той же иконкой. Мы можем скрыть их, когда они используются как декоративные элементы, или подписать, когда это нужно. Круто!

Взгляните на демо. Нет никакой разницы между тем, как выглядят иконки, но разница в количестве кода, используемого для их отображения, огромна.

Заключение Скопировать ссылку

Надеюсь, что этот материал был вам полезен, и вы прямо сейчас готовы использовать SVG-иконки в своих проектах. В этой маленькой статье невозможно объяснить все основные идеи. Чтобы помочь вам глубже погрузиться в океан SVG, я собрал здесь несколько ссылок на другие статьи и книги по этой теме.

Дополнительные источники Скопировать ссылку

  • Сара Суайдан написала «An overview of SVG Sprite Creation Techniques».
  • Она также объясняет, как перейти от иконочного шрифта к SVG-спрайтам в «Making the Switch Away from Icon Fonts to SVG».
  • Хезер Мильориси рассказывает обо всех упущенных здесь подробностях, как сделать SVG доступным для всех в «Accessible SVG».
  • Сара Дрэснер написала замечательную книгу об SVG-анимации. В ней есть все советы, которые могут понадобиться для анимации SVG-графики.
  • Скотт Охара написал подробную статью о том, когда использовать role=»none» или role=»presentation» , а когда aria-hidden=»true» .
  • Крис Койер собрал вместе довольно много полезной информации и статей на эту тему в «SVG Compendium».
  • Он также написал книгу «Practical SVG» для A Book Apart.

Благодарность Скопировать ссылку

Знания, накопленные мной за то время, которое мы говорим об SVG, а также о доступности, получены из книг, постов в блогах и учебных пособий. Также я слежу за профилями людей в социальных сетях, которые работают в этой области и написали эти самые книги, посты и пособия. Конечно же помогли в этом и бесконечные ковыряния в коде, а также написание разных вещей и их ломание.

Итак, без лишних слов, спасибо Леони Уотсон, Лоре Калбаг, Лии Веру, Саре Суайдан, Саре Дрэснер, Вал Хед, Серене Дэвис, Марси Саттон, Кэри Фишер, Зоуи Гилленуотер, Хезер Мильориси, Мэлори ван Ахтерберг, Стиву Фолкнеру, Патрику Лауке, Хейдону Пикерингу, Нилу Милликену, Николасу Стинхауту, Марко Цехе, Хьюго Жироделю, Гуннару Биттерсману, Эрику Бэйли, Алану Далтону, Крису Койеру, Брюсу Лоусону, Аарону Густавсону, Скотту Охаре, всей Paciello Group, A List Apart и A Book Apart, Khan Academy, командам Pa11y и tenon.io, а также тем, кого я забыл здесь упомянуть.

Спасибо всем тем, кто (надеюсь) никогда не сдаётся, и объясняет другим (и мне), почему доступность важна, и как сделать интернет более инклюзивным местом.

The Many Ways to Change an SVG Fill on Hover (and When to Use Them)

SVG is a great format for icons. Vector formats look crisp and razor sharp, no matter the size or device — and we get tons of design control when using them inline. SVG also gives us another powerful feature: the ability to manipulate their properties with CSS. As a result, we can make quick and simple interactions where it used to take crafty CSS tricks or swapping out entire image files. Those interactions include changing color on hover states. It sounds like such a straightforward thing here in 2019, but there are actually a few totally valid ways to go about it — which only demonstrates the awesome powers of SVG more. First off, let’s begin with a little abbreviated SVG markup:

Target the .icon class in CSS and set the SVG fill property on the hover state to swap colors.

.icon:hover

This is by far the easiest way to apply a colored hover state to an SVG. Three lines of code! SVGs can also be referenced using an tag or as a background image. This allows the images to be cached and we can avoid bloating your HTML with chunks of SVG code. But the downside is a big one: we no longer have the ability to manipulate those properties using CSS. Whenever I come across non-inline icons, my first port of call is to inline them, but sometimes that’s not an option. I was recently working on a project where the social icons were a component in a pattern library that everyone was happy with. In this case, the icons were being referenced from an element. I was tasked with applying colored :focus and :hover styles, without adjusting the markup. So, how do you go about adding a colored hover effect to an icon if it’s not an inline SVG?

  • brightness();
  • contrast();
  • grayscale();
  • invert();
  • opacity();
  • saturate();
  • sepia();
  • hue-rotate();
  • blur();
  • drop-shadow();

All filters take a value which can be changed to adjust the effect. In most cases, this value can be expressed in either a decimal or percent units (e.g. brightness(0.5) or brightness(50%) ).

Straight out of the box, there’s no CSS filter that allows us to add our own specific color.
We have hue-rotate() , but that only adjusts an existing color; it doesn’t add a color, which is no good since we’re starting with a monochromatic icon.

The game-changing bit about CSS filters is that we don’t have to use them in isolation. Multiple filters can be applied to an element by space-separating the filter functions like this:

.icon:hover

If one of the filter functions doesn’t exist, or has an incorrect value, the whole list is ignored and no filter will be applied to the element.

When applying multiple filter functions to an element, their order is important and will affect the final output. Each filter function will be applied to the result of the previous operation.

So, in order to colorize our icons, we have to find the right combination.

To make use of hue-rotate() , we need to start off with a colored icon. The sepia() filter is the only filter function that allows us to add a color, giving the filtered element a yellow-brown-y tinge, like an old photo.

The output color is dependent on the starting tonal value:

In order to add enough color with sepia() , we first need to use invert() to convert our icon to a medium grey:

.icon:hover

We can then add the yellow/brown tone with sepia() :

.icon:hover

…then change the hue with hue-rotate() :

.icon:hover

Once we have the rough color we want, we can tweak it with saturation() and brightness() :

.icon:hover

I’ve made a little tool for this to make your life a little easier, as this is a pretty confusing process to guesstimate.

Even with the tool, it’s still a little fiddly, not supported by Internet Explorer, and most importantly, you’re unable to specify a precise color.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop
Chrome Firefox IE Edge Safari
18* 35 No 79 6*
Mobile / Tablet
Android Chrome Android Firefox Android iOS Safari
121 122 4.4* 6.0-6.1*

So, what do we do if we need a specific hex code?

If we need more precise control (and better browser support) than CSS filters can offer, then it’s time to turn to SVG.

Filters originally came from SVG. In fact, under the hood, CSS filters are just shortcuts to SVG filters with a particular set of values baked in.

Unlike CSS, the filter isn’t predefined for us, so we have to create it. How do we do this?

This is the syntax to define a filter:

  . . . 

Filters are defined by a element, which goes inside the section of an SVG.

SVG filters can be applied to SVG content within the same SVG document. Or, the filter can be referenced and applied to HTML content elsewhere.

To apply an SVG filter to HTML content, we reference it the same way as a CSS filter: by using the url() filter function. The URL points to the ID of the SVG filter.

.icon:hover

The SVG filter can be placed inline in the document or the filter function can reference an external SVG. I prefer the latter route as it allows me to keep my SVG filters tidied away in an assets folder.

.icon:hover < filter: url('assets/your-SVG.svg#id-of-your-filter'); >

Back to the element itself.

Right now, this filter is empty and won’t do anything as we haven’t defined a filter primitive. Filter primitives are what create the filter effects. There are a number of filter primitives available to us, including:

Just like with CSS filters, we can use them on their own or include multiple filter primitives in the tag for more interesting effects. If more than one filter primitive is used, then each operation will build on top of the previous one.

For our purposes we’re just going to use feColorMatrix , but if you want to know more about SVG filters, you can check out the specs on MDN or this (in progress, at the time of this writing) article series that Sara Soueidan has kicked off.

feColourMatrix allows us to change color values on a per-channel basis, much like channel mixing in Photoshop.

This is what the syntax looks like:

    . 

The color-interpolation-filters attribute specifies our color space. The default color space for filter effects is linearRGB, whereas in CSS, RGB colors are specified in the sRGB color space. It’s important that we set the value to sRGB in order for our colors to match up.

Let’s have a closer look at the color matrix values.

The first four columns represent the red, green and blue channels of color and the alpha (opacity) value. The rows contain the red, green, blue and alpha values in those channels.

The M column is a multiplier — we don’t need to change any of these values for our purposes here. The values for each color channel are represented as floating point numbers in the range 0 to 1.

We could write these values as a CSS RGBA color declaration like this:

rgba(255, 255, 255, 1)

The values for each color channel (red, green and blue) are stored as integers in the range 0 to 255. In computers, this is the range that one 8-bit byte can offer.

By dividing these color channel values by 255, the values can be represented as a floating point number which we can use in the feColorMatrix .

And, by doing this, we can create a color filter for any color with an RGB value!

Like teal, for example:

rgba(0, 128, 128, 1). 128%255=0.50

This SVG filter will only impart color to icons with a white fill, so If we have an icon with a black fill, we can use invert() to convert it to white before applying the SVG filter.

.icon:hover < filter: invert(100%) url('assets/your-SVG.svg#id-of-your-filter'); >

If we just have a hex code, the math is a little trickier, although there are plenty of hex-to-RGBA converters out there. To help out, I’ve made a HEX to feColorMatrix converter.

Have a play around, and happy filtering!

Пути (paths)

Элемент («путь»)– наиболее мощный элемент в библиотеке основных форм SVG. С его помощью можно создавать отрезки, кривые, дуги и многое другое.

С помощью элементов создают сложные формы, объединяя многочисленные прямые и кривые линии. Сложные формы из одних только прямых линий можно создавать и через элемент polyline . Хотя результаты работы обоих элементов могут быть похожи, элемент polyline отображает кривые как много маленьких прямых линий, что не очень хорошо масштабируется до больших размеров. Хорошее понимание path важно при рисовании SVG. При создании сложных paths не рекомендуется использовать XML или текстовые редакторы – понимание, как они работают, позволит установить и исправить проблемы с отображением SVG.

Форма элемента path определяется одним атрибутом: d (смотри подробности в основные формы). Атрибут d содержит серию команд и параметров, используемых этими командами. Мы опишем доступные команды и покажем примеры того, что они делают.

Каждая команда обозначается специальной буквой. Например, нам надо переместиться в точку с координатами (10,10). Команда «Передвинуть к» вызывается буквой M. Когда синтаксический анализатор наталкивается на эту команду, он знает, что необходимо переместиться к указанной точке. Итак, для перемещения к точке (10,10) используется команда «M 10 10», и далее синтаксический анализатор переходит к следующей команде.

Все команды существуют в двух вариантах: вызов команды с заглавной буквы обозначает абсолютные координаты на странице, а команда со строчной буквой -относительные (например, перемещение от последней точки на 10px вверх и 7px влево).

Координаты в атрибуте d всегда пишутся без указания единиц измерения и находятся в системе пользовательских координат (обычно это пиксели). Позже мы рассмотрим, как элемент paths может быть трансформирован для других нужд.

Команды линии

Существуют пять команд линии для узлов . Первая команда — это «Переместиться к», или M, описанная выше. В качестве параметров она принимает координаты точки, к которой перемещается. Если курсор уже был где-либо на странице, между старым и новым местом линия не появится. Команда «Переместиться к» используется в начале элемента для указания точки, откуда начнётся рисование, например:

M x y
m dx dy

Следующий пример рисует одну только точку (10,10). Заметьте, однако, что при обычном использовании она вообще не была бы видна.

svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"> path d="M10 10"/> circle cx="10" cy="10" r="2" fill="red"/> svg> 

Существуют три команды, которые рисуют линии. Самая общая — команда «Линия к», вызываемая буквой L. Эта команда принимает два параметра — координаты точки x и y — и рисует линию от текущего положения к этой точке.

L x y (или l dx dy)

Для рисования горизонтальных и вертикальных линий есть две укороченные формы . H рисует горизонтальную линию, а V рисует вертикальную линию. Обе команды используют только один аргумент, так как они движутся только в одном направлении.

H x (или h dx) V y (или v dy)

Начнём с рисования простой формы, например, прямоугольника (такого же, какой проще нарисовать с помощью элемента ). Он состоит только из горизонтальных и вертикальных линий:

svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"> path d="M10 10 H 90 V 90 H 10 L 10 10"/> circle cx="10" cy="10" r="2" fill="red"/> circle cx="90" cy="90" r="2" fill="red"/> circle cx="90" cy="10" r="2" fill="red"/> circle cx="10" cy="90" r="2" fill="red"/> svg> 

Нашу запись в примере выше можно немного сократить , используя команду «Закрыть путь», Z . Эта команда рисует прямую линию от текущего положения обратно к первой точке пути. Она часто встречается в конце узла пути, хотя и не всегда. Для неё регистр буквы не важен.

Z (или z)

Таким образом наш путь из примера можно сократить до:

path d="M10 10 H 90 V 90 H 10 Z" fill="transparent" stroke="black"/> 

Точно такую же картину можно получить с помощью относительных форм этих команд. Как уже говорилось, относительные команды вызываются использованием букв нижнего регистра и перемещают курсор относительно его последнего положения, а не к точным координатам . В нашем примере, поскольку размеры нашего квадрата — 80 x 80, элемент можно записать так:

path d="M10 10 h 80 v 80 h -80 Z" fill="transparent" stroke="black"/> 

Путь начнётся от точки (10,10), пойдёт горизонтально на 80 точек вправо, затем 80 точек вниз, затем 80 точек влево, и затем обратно к старту.

Возможно, в этих примерах было бы проще использовать элементы или . Однако, пути используются при рисовании SVG настолько часто, что многим разработчикам может быть удобнее использовать их вместо других элементов. Нет никакой разницы в производительности при использовании того или другого.

Команды кривых линий

Существует три различных команды, которые вы можете использовать для создания плавных кривых линий. Две из этих кривых — кривые Безье, а третья — «дуга», или часть окружности. Вы, возможно, уже имели практический опыт с кривыми Безье, если работали с путями (paths) в программах lnkscape, Illustrator или Photoshop. Для полного описания математических понятий о кривых Безье, попробуйте пройти по ссылке на Wikipedia. Информации о кривых Безье слишком много, чтобы попытаться охватить её здесь. Существует бесчисленное множество различных типов кривых Безье, но только две простые доступны для элементов путей: кубическая, C, и квадратная, Q.

Кривые Безье

Кубическая кривая, C, представляет собой немного более сложную кривую. Кубическая Безье принимает две контрольные точки для каждой точки. Таким образом, чтобы создать кубическую кривую Безье, вам необходимо указать три набора координат.

C x1 y1, x2 y2, x y (or c dx1 dy1, dx2 dy2, dx dy)

Последний набор координат (x,y) это точка, в которой заканчивается линия. Две другие — контрольные точки. (x1,y1) контрольная точка для начала вашей кривой, а (x2,y2) для конца вашей кривой. Если вы знакомы с вычислительной алгеброй, контрольные точки в описывают наклон вашей линии в каждой точке. Функция Безье создаёт плавную кривую, которая ведёт от наклона, который вы установили в начале вашей линии к наклону на другом конце.

Cubic Bézier Curves with grid

svg width="190" height="160" xmlns="http://www.w3.org/2000/svg"> path d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent"/> path d="M70 10 C 70 20, 120 20, 120 10" stroke="black" fill="transparent"/> path d="M130 10 C 120 20, 180 20, 170 10" stroke="black" fill="transparent"/> path d="M10 60 C 20 80, 40 80, 50 60" stroke="black" fill="transparent"/> path d="M70 60 C 70 80, 110 80, 110 60" stroke="black" fill="transparent"/> path d="M130 60 C 120 80, 180 80, 170 60" stroke="black" fill="transparent"/> path d="M10 110 C 20 140, 40 140, 50 110" stroke="black" fill="transparent"/> path d="M70 110 C 70 140, 110 140, 110 110" stroke="black" fill="transparent"/> path d="M130 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, то подразумевается, что текущая позиция курсора используется как первая контрольная точка. Пример синтаксиса показан ниже. В фигуре слева контрольные точки показаны красным, а подразумеваемая контрольная точка — синим.

ShortCut_Cubic_Bezier_with_grid.png

svg width="190" height="160" xmlns="http://www.w3.org/2000/svg"> path d="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="black" fill="transparent"/> svg> 

Другой тип кривой Безье — квадратичная кривая, задаётся командой Q. Квадратичная кривая проще, чем кубическая: для неё требуется только одна контрольная точка, которая определяет наклон кривой как в начальной, так и в конечной точке. Она принимает два аргумента: контрольную точку и конец кривой.

Q x1 y1, x y (or q dx1 dy1, dx dy)

Quadratic Bézier with grid

svg width="190" height="160" xmlns="http://www.w3.org/2000/svg"> path d="M10 80 Q 95 10 180 80" stroke="black" fill="transparent"/> svg> 

Как и в случае кубической кривой Безье, существует сокращение для соединения нескольких квадратичных кривых Безье -T.

T x y (or t dx dy)

Как и ранее, сокращение смотрит на предыдущую контрольную точку, которую вы использовали, и выводит из неё новую. Это означает, что после первой контрольной точки вы можете делать довольно сложные фигуры, указав только конечные точки.

Примечание: Обратите внимание, что это работает только в том случае, если предыдущей командой была команда Q или T. Если это не так, то контрольная точка считается той же, что и предыдущая, и вы нарисуете только линии.

Shortcut_Quadratic_Bezier_with_grid.png

svg width="190" height="160" xmlns="http://www.w3.org/2000/svg"> path d="M10 80 Q 52.5 10, 95 80 T 180 80" stroke="black" fill="transparent"/> svg> 

Обе кривые дают похожие результаты, но кубическая кривая позволяет больше свободы в том, как должна выглядеть кривая. Решение, какую кривую использовать — ситуационное и зависит от количества симметрии в линиях.

Дуги

Другой тип кривых линий, которые можно создать с помощью SVG — дуга (команда A). Дуги — секции кругов или эллипсов. При заданных x- и y-радиусах есть два эллипса, которые могут соединяться любыми двумя точками (пока они находятся внутри радиуса круга). Вдоль любого из этих кругов есть два пути, которые могут использовать для соединения точек, так что в любой ситуации возможно 4 дуги.

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

В начале элемент дуги принимает два аргумента радиусов. Если нужно, обратитесь к разделу Эллипсы, чтобы увидеть, как они работают. Последние два аргумента предназначены для обозначения координат окончания дуги. Вместе эти четыре значения определяют основную структуры дуги.

Третий параметр описывает поворот дуги. См. пример ниже

SVGArcs_XAxisRotation_with_grid

svg width="320" height="320" xmlns="http://www.w3.org/2000/svg"> path d="M10 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-asix-rotation = 0, а это означает, что эллипс, по которому проходит дуга (показан серым) расположен вертикально. Во второй дуге параметр x-asix-rotation = -45. Это поворачивает эллипс так, что направление его малой оси совпадает с направлением пути, как это видно на рисунке выше.

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

Show the 4 arcs on the Ellipse example

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"/> circle cx="150.71" cy="170.29" r="2" fill="red"/> circle cx="110" cy="215" r="2" fill="red"/> ellipse cx="144.931" cy="229.512" rx="36" ry="60" fill="transparent" stroke="blue"/> ellipse cx="115.779" cy="155.778" rx="36" ry="60" fill="transparent" stroke="blue"/> svg> 

Заметьте, что каждый голубой эллипс сформирован двумя дугами, в зависимости от того движетесь ли вы по часовой или против часовой стрелке. Каждый эллипс имеет короткую и длинную дуги. Оба эллипса просто зеркальные отражения друг друга. Они отражены вдоль линии, сформированной start->end точками.

Если start->end точки расположены далеко и не попадают в пределы градусов эллипсов по x и y, то в этом случае радиусы эллипсов будут увеличены до величины, нужной чтобы достичь точек start->end. Интерактивный codepen внизу этой страницы наглядно это демонстрирует. Для определения достаточны ли велики радиусы ваших эллипсов чтобы требовать увеличения, вам нужно решить систему уравнений подобную этой на wolfram alpha. Это вычисление для non-rotated эллипса с start->end (110, 215)->(150.71, 170.29). Решением, (x, y), является центр эллипса(ов). Следующее вычисление для non-rotated эллипса с start->end (110, 215)->(162.55, 162.45). Решение будет мнимым если радиусы ваших эллипсов слишком малы. Решение содержит небольшой мнимый компонент потому, что эллипсы были лишь слегка расширены.

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

svg width="325" height="325" xmlns="http://www.w3.org/2000/svg"> path d="M80 80 A 45 45, 0, 0, 0, 125 125 L 125 80 Z" fill="green"/> path d="M230 80 A 45 45, 0, 1, 0, 275 125 L 275 80 Z" fill="red"/> path d="M80 230 A 45 45, 0, 0, 1, 125 275 L 125 230 Z" fill="purple"/> path d="M230 230 A 45 45, 0, 1, 1, 275 275 L 275 230 Z" fill="blue"/> svg> 

Последние два аргумента, если вы ещё не догадались, обозначают координаты x и y, где заканчивается дуга. Дуги — лёгкий способ создавать части кругов или эллипсов в ваших рисунках. Например, круговая диаграмма требует отдельную дугу для каждого куска диаграммы.

Если вы переходите в SVG из Canvas а, дуги могут быть самой трудной вещью для изучения, но они также очень мощные. Т.к. начальная и конечные точки для любого пути, обходящего круг, одно и то же место, существует бесконечное количество кругов, которые могут быть выбраны и действительный путь не определён. Возможно приблизить их, сделав начальную и конечную точку пути слегка разными и соединив их с другими сегментами пути. В этой точке, часто проще использовать настоящий круг или эллипс. Это интерактивное демо может помочь понять основные принципы SVG-дуг: http://codepen.io/lingtalfi/pen/yaLWJG (протестировано только в Chrome и Firefox, может не работать в вашем браузере)

  • « Предыдущая статья
  • Следующая статья »

Found a content problem with this page?

  • Edit the page on GitHub.
  • Report the content issue.
  • View the source on GitHub.

This page was last modified on 5 дек. 2023 г. by MDN contributors.

Курсы javascript

а можно ли сделать так что бы можно было присвоить новый а при повторном click вернуть старый ?

12.11.2019, 10:44
Регистрация: 27.05.2010
Сообщений: 33,050
Максим Ученик,

   Untitled  button, svg  btn.onclick = function()  

12.11.2019, 10:51
Интересующийся
Регистрация: 13.08.2019
Сообщений: 25
Огромное спасибо . именно то что надо
« Использование дочерних элементов из родительского? | обработчик нескольких элементов »

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как изменить заливку SVG user_name Элементы интерфейса 2 22.04.2015 00:36
Как сделать так, чтобы значение переменной не возвращалось на исходное значение? E>|

Общие вопросы Javascript 1 21.12.2014 15:26
Присвоить value значение или как? qazibum Элементы интерфейса 17 30.08.2012 19:50
Как в IE динамически установить значение события onClick? Гость Элементы интерфейса 6 16.01.2011 23:46
Переменная от переменной или как к имени переменной конкатенировать значение другой Aderba jQuery 5 12.11.2008 15:25

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *