Как покрасить svg при помощи css
Перейти к содержимому

Как покрасить svg при помощи css

  • автор:

Редактируемая система SVG-иконок

Существуют множество способов создания системы SVG-иконок (SVG Icon System), но один из методов, который использует возможности Vue, — это создание редактируемых встроенных иконок в виде компонентов. Некоторые из преимуществ такого подхода:

  • Их легко редактировать «на лету»
  • Они анимируются
  • Вы можете использовать обычные входные параметры и значения по умолчанию для сохранения стандартного размера или изменения их, если это нужно
  • Они встраиваемые, поэтому HTTP-запросы не требуются
  • Они могут быть доступны динамически

Сначала мы создадим каталог для всех иконок и назовём их в стандартизированном подходе для облегчения их поиска:

Вот репозиторий с примером для начала работы, где вы увидите готовую настройку: https://github.com/sdras/vue-sample-svg-icons/

Сайт документации

Мы создадим компонент базовой иконки ( IconBase.vue ), который использует слот.

template> 
svg xmlns="http://www.w3.org/2000/svg"
:width="width"
:height="height"
viewBox="0 0 18 18"
:aria-labelledby="iconName"
role="presentation"
>
title
:id="iconName"
lang="en"
>{{iconName}} icon title>
g :fill="iconColor">
slot />
g>
svg>
template>

Вы можете использовать эту базовую иконку как есть, однако вам нужно обновить viewBox в зависимости от viewBox ваших иконок. В базовом компоненте мы устанавливаем width , height , iconColor и имя иконки как входные данные так, что он может динамически обновляться. Имя используется как для содержимого , так и для его id для лучшей доступности.

Наш скрипт будет выглядеть следующим образом: у нас будут некоторые значения по умолчанию, поэтому иконка будет отрисовываться всегда одинаково, пока мы не изменим её:

export default { 
props: {
iconName: {
type: String,
default: 'box'
},
width: {
type: [Number, String],
default: 18
},
height: {
type: [Number, String],
default: 18
},
iconColor: {
type: String,
default: 'currentColor'
}
}
}

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

Мы можем использовать его следующим образом, с единственным содержимым IconWrite.vue , содержащим пути внутри иконок:

icon-base icon-name="write">icon-write /> icon-base> 

Теперь, если мы захотим несколько иконок с различными размерами, это сделать довольно просто:

p> 

icon-base

width="12"
height="12"
icon-name="write"
>icon-write /> icon-base>

icon-base icon-name="write">
icon-write /> icon-base>

icon-base

width="30"
height="30"
icon-name="write"
>icon-write /> icon-base>
p>

Анимируемые иконки

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

 
@click="startScissors"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 100"
width="100"
height="100"
aria-labelledby="scissors"
role="presentation"
>
lang="en"
>
Анимированная иконка с ножницами
fill="#fff"
d="M0 0h100v100H0z"
/>


.


.
import { TweenMax, Sine } from 'gsap'

export default {
methods: {
startScissors( ) {
this.scissorAnim(this.$refs.rightscissor, 30)
this.scissorAnim(this.$refs.leftscissor, -30)
},
scissorAnim(el, rot) {
TweenMax.to(el, 0.25, {
rotation: rot,
repeat: 3,
yoyo: true,
svgOrigin: '50 45',
ease: Sine.easeInOut
})
}
}
}

Мы применяем refs для группы путей, которые нам нужно переместить, и по мере того, как обе стороны ножниц должны перемещаться вместе, мы создаём функцию, которую повторно используем при обращении к refs . Использование GreenSock помогает разрешить поддержку анимации и проблемы с transform-origin во всех браузерах.

Довольно легко сделано! И легко обновлять «на лету».

Вы можете посмотреть больше анимационных примеров в репозитории

Дополнительные замечания

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

Когда не следует этого делать

Эта система SVG-иконок действительно полезна, когда у вас есть несколько иконок, которые используются по-разному на всём сайте. Если вы дублируете одну и ту же иконку много раз на одной странице (например, во всех строках гигантской таблицы в качестве иконки удаления), может имеет больше смысла сделать спрайты, скомпилированные в лист спрайта, и использовать теги для их загрузки.

Альтернативные варианты

Другие инструменты для помощи в управлении SVG-иконками включают:

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

Обнаружили ошибку или хотите добавить что-то своё в документацию? Измените эту страницу на GitHub! Опубликовано на Netlify .

Создание системы SVG-иконок с помощью React

Недавно я прошла обучение ReactJS у Майкла Джексона и Райана Флоренса. И мне очень понравилось, частично потому, что я нашла ответы на множество вопросов про SVG и React. В том, что касается работы с Реактом и SVG, есть много мелочей, которые еще не совсем поддерживаются. Одной из главных загадок для меня был элемент , поскольку большинство систем SVG-иконок строятся именно на нём.

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

Примечание: стоит отметить, что поддержка use недавно улучшилась, но мне показалось, что она по меньшей мере не стабильна и у нее есть другие проблемы с маршрутизацией и XML. Здесь мы рассмотрим более аккуратный способ.

Что такое ?

Для тех, кто не знает, как обычно строятся системы SVG-иконок, это работает примерно так. Элемент клонирует копию любого другого элемента SVG-фигуры с помощью ссылки на ID в атрибуте xlink:href , и по-прежнему управляет им, без повторения всех данных пути. Может возникнуть вопрос, почему бы не подключать SVG тегом . В принципе, можно, но тогда каждая иконка запрашивалась бы отдельно и вы бы не смогли менять части SVG, такие, как цвет fill .

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

У Джони Трайтел есть отличная статья про use и SVG-иконки, а Крис Койер также написал ещё одну потрясающую статью здесь на CSS-Tricks.

Вот небольшой пример, как может выглядеть разметка:

Зачем заморачиваться с SVG-иконками?

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

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

  • Иконочные шрифты плохо сочетаются с доступностью. В SVG можно добавлять заголовок и теги ARIA, что даёт огромное преимущество доступности, особенно в тех случаях, когда иконка — один-единственный источник информативной навигации. Подумайте о слепых, о людях с дислексией или пожилых (когда-нибудь вы сами станете пожилыми, хочется надеяться, так что если вам сейчас безразлична эта группа, то сделайте это хотя бы для кармы! Но серьезно, подумайте о пожилых.)
  • Иконочные шрифты недостаточно четкие на некотрых экранах. Этого можно избежать, применив какое-то хитрое сглаживание шрифтов в CSS, но есть нюанс: его трудно переопределить, не выключив сглаживание шрифтов полностью. SVG в целом четче, рисование — это его предназначение.
  • Иконочные шрифты не срабатывают в изрядной доле случаев. Большинство моих знакомых разработчиков сталкиваются со сценариями с крестиком отсутствующего символа в рамке, и есть множество ситуаций, где иконочные шрифты в отличие от SVG могут не сработать. Будь то CORS-ограничения или Opera mini, это головная боль.
  • Иконочные шрифты трудно позиционировать. Это изображение, которое позиционируется с помощью стилей шрифта. И этим всё сказано. Нельзя анимировать их части без кучи хаков. SVG предлагает управляемый DOM для анимации или окрашивания частей иконки. Это не всегда нужно, но такая возможность уж точно не помешает.

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

Краткая выжимка: в Реакте не нужен

После того, как Майкл терпеливо выслушал мой рассказ про то, как мы используем , и я показала ему пример системы иконок, его решение было простым: всё это не нужно.

Подумайте вот о чем: единственная причина, по которой мы определяли иконки, чтобы затем повторно использовать их (обычно в виде в ) — чтобы не пришлось повторяться и можно было обновлять SVG-контуры в одном месте. Но Реакт уже позволяет это. Нужно просто создать компонент:

// Иконка const IconUmbrella = React.createClass( < render() < return ( Иконка зонта  ) > >); // что делает это многоразовым компонентом для других представлений 

И можно использовать его снова и снова, но в отличие от старого способа с , нет дополнительного HTTP-запроса.

Возможно, в примере выше вы заметили две SVG-шные штуки. Первое, у меня нет этого вывода:

Или даже этого у самого тега SVG:

Это потому, что я оптимизировала свой SVG с помощью SVGOMG или SVGO прежде чем добавить разметку. Настоятельно рекомендую делать так же, поскольку можно прилично уменьшить размер SVG. Обычно у меня выходит около 30% процентов, но бывает до 60% и выше.

Ещё вы, возможно, заметили, что я добавила заголовок и тег ARIA. Это поможет скринридерам произнести иконки для тех, кто использует вспомогательные технологии.

 Иконка зонта 

Поскольку этот id должен быть уникальным, можно передать props в экземляры иконки и распространится на заголовок и тег aria:

// Приложение const App = React.createClass( < render() < return ( 
) > >); // Иконка const IconOffice = React.createClass( < . render() < return ( height= viewBox="0 0 188.5 188.5" aria-labelledby=> . ) > >); ReactDOM.render(, document.querySelector("#main"));

Возможно, самое интересное

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

Вдобавок к этому: можно очень просто на лету перекрашивать и анимировать части иконок с помощью SVG и props.

Меняем это на лету

Возможно, вы заметили, что мы ещё не настраиваем его на лету, а ведь отчасти ради этого мы и выбрали SVG в первую очередь, не так ли? Можно объявить в иконке некоторые props по умолчанию, а затем изменять их, например, так:

// Приложение const App = React.createClass( < render() < return ( 
) > >); // Иконка const IconOffice = React.createClass(< getDefaultProps() < return < width: '100', height: '200' >; >, render() < return ( height= xmlns="http://www.w3.org/2000/svg" viewBox="0 0 188.5 188.5" aria-labelledby="title"> Office Icon . ) > >); ReactDOM.render(, document.querySelector("#main"));

Разовъём эту идею и немного изменим внешний вид в зависимости от экземпляра. Для этого можно использовать props и объявить некоторые props по умолчанию.

Я люблю SVG, поскольку теперь у нас есть управляемый DOM, так что давайте изменим цвет некоторых фигур на лету с помощью fill . Не забывайте, если раньше вы привыкли работать с иконочными шрифтами, что теперь вы управляете цветом не с помощью color , а с помощью fill . Можно посмотреть это в действии во втором примере ниже, где у книг изменился цвет. Также мне нравится возможность анимировать эти части на лету, ниже мы обернули его в div, чтобы легко анимировать его с помощью CSS (чтобы увидеть анимацию, возможно придётся нажать кнопку «Rerun»)

// Приложение const App = React.createClass( < render() < return ( 
) > >); // Иконка const IconOffice = React.createClass(< getDefaultProps() < return < width: '100', height: '200', bookfill: '#f77b55', bookside: '#353f49', bookfront: '#474f59' >; >, render() < return ( height= viewBox="0 0 188.5 188.5" aria-labelledby="title"> Иконка офиса d="M50.3 77.5h10.4v57.18H50.3z"/> d="M60.7 77.5h38.9v57.19H60.7z"/> . ) > >); ReactDOM.render(, document.querySelector("#main"));
.switcher .office < #bulb < animation: switch 3s 4 ease both; >#background < animation: fillChange 3s 4 ease both; >> @keyframes switch < 50% < opacity: 1; >> @keyframes fillChange < 50% < fill: #FFDB79; >>

Один мой замечательный коллега из Trulia, Маттиа Тосо, также рекомендовал классный и гораздо более чистый способ объявления всех этих props. Здесь можно избавиться от повторения this.props , объявив всё, что мы будем использовать, через const, а в дальнейшем просто подставляя отдельные переменные:

render() < const < height, width, bookfill, bookside, bookfront >= this.props; return ( height= viewBox="0 0 188.5 188.5" aria-labelledby="title"> Иконка офиса    d="M50.3 77.5h10.4v57.18H50.3z"/> d="M60.7 77.5h38.9v57.19H60.7z"/>

Можно также сделать это ещё круче, объявив propTypes в используемом props. PropTypes невероятно полезны, поскольку они как живая документация для повторно используемых props .

propTypes: < width: string, height: string, bookfill: string, bookside: string, bookfront: string >,

Если использовать их неправильно, как примере ниже, то в консоли появится ошибка, которая не помешает коду запуститься, но сообщит вашим коллегам (или вам самим) о неправильном применении props. Здесь я использую для props число вместо строки.

 bookside="#39B39B" bookfront="#76CEBD" />

И всплывает такая ошибка:

props-error

Ещё компактнее с React 0.14+

В новейших версиях Реакта можно избавиться от части этого хлама и упростить код ещё больше, но только в случае очень «глупого» компонента, который, например, не принимает методы жизненного цикла. Иконки отлично подходят для этого, поскольку мы в основном просто отображаем их, так что давайте попробуем. Можно избавиться от React.createClass и написать компоненты в виде простых функций. Это довольно мило, если вы уже давно используете JavaScript, но не очень знакомы с самим Реактом — это напоминает функции, к котрым мы все привыкли. Давайте почистим props ещё лучше и заново используем иконку зонта, как мы бы сделали это на сайте.

// Приложение function App() < return ( 
) > // Шапка function Header() < return (

Привет, мир!

) > // Иконка function IconUmbrella(props) < const umbrellafill = props.umbrellafill || 'orangered' return ( Umbrella d="M27 14h5c0-1.105-1.119-2-2.5-2s-2.5 0.895-2.5 2v0zM27 14c0-1.105-1.119-2-2.5-2s-2.5 0.895-2.5 2c0-1.105-1.119-2-2.5-2s-2.5 0.895-2.5 2v0 14c0 1.112-0.895 2-2 2-1.112 0-2-0.896-2-2.001v-1.494c0-0.291 0.224-0.505 0.5-0.505 0.268 0 0.5 0.226 0.5 0.505v1.505c0 0.547 0.444 0.991 1 0.991 0.552 0 1-0.451 1-0.991v-14.009c0-1.105-1.119-2-2.5-2s-2.5 0.895-2.5 2c0-1.105-1.119-2-2.5-2s-2.5 0.895-2.5 2c0-1.105-1.119-2-2.5-2s-2.5 0.895-2.5 2c0-5.415 6.671-9.825 15-9.995v-1.506c0-0.283 0.224-0.499 0.5-0.499 0.268 0 0.5 0.224 0.5 0.499v1.506c8.329 0.17 15 4.58 15 9.995h-5z"/> ) > ReactDOM.render(, document.querySelector("#main"));

Системы иконок на базе SVG в Реакте просто замечательны и легко расширяемы, с ними нужно меньше HTTP-запросов, и их будет легче поддерживать в будущем, поскольку можно будет полностью обновить вывод, не меняя разметку в нескольких местах. Можно улучшить производительность, выбрав то, что нам нужно. Можно менять их на лету с помощью props для цвета и даже добавить CSS-анимацию. Кроме того, можно также сделать их доступными для скринридеров, что делает Реакт и системы SVG-иконок по-настоящему классным способом добавления иконок в веб-приложения.

P.S. Это тоже может быть интересно:
  • Не боритесь с каскадом, управляйте им!
  • CSS-выражения от контейнера для дизайнеров
  • Тёмная сторона CSS: выходим за рамки и взрываем звезды с border-image и градиентами

Если вам понравилась статья, поделитесь ей!

Vue + SVG + �� = ��

В проектах чаще всего встречаются “иконочные” шрифты (например, Font Awesome, с пятой версии даже SVG сразу есть в комплекте). Но попался один проект, где решено использовать только SVG-иконки (причём экспортировались они из Figma, и зачастую с небольшими косяками). Понятно было, что через некоторое время потребуется обновлять на исправленные версии иконок. Некоторые иконки уже были “спрятаны” внутри спрайта и непонятно какие там уже были.

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

Чего хочется…

  • Чтобы SVG-файлы лежали в одном каталоге, где мы сможем легко видеть превью всех иконок (в macOS для превью можно установить бесплатный Gaplin), найти нужную и, например, обновить.
  • Чтобы мы могли подключить иконку по имени файла или пути.
  • Чтобы можно было подключить иконку на страницу одним тегом, как, например, вставляем иконку из Font Awesome.
  • Чтобы не приходилось заморачиваться с разметкой, поисками ID нужной иконки в спрайте или разбираться какие иконки там есть.
  • Чтобы можно было стилизовать наши иконки в реальном времени, а также динамически менять одну иконку на другую.
  • Чтобы иконки на этапе сборки автоматически собирались в один файл спрайта, а не загружались десятком запросов.

Как подключить SVG на страницу

Есть разные варианты подключения SVG на страницу (если какие-то варианты забыл, пишите), посмотрим что они из себя представляют и какие есть плюсы и минусы.

Тег

Самый простой вариант подключения — через тег .

  • В несжатом виде 11,34+14,7+32,71+1,06 = 59,81 КБайт
  • С минификацией и Gzip 1,81+2,24+3,86 = 7,91 КБайт

Что удалось?

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

Что ещё не идеально?

  • Все SVG-файлы должны лежать в том каталоге, который явно прописан в компоненте для динамического require.
  • Для более сложных стилизаций иконок, например необходимости менять stroke может потребоваться доработка решение или даже передачу функции стилизации через входной параметр. Что не так удобно, просто тега компонента будет недостаточно.
  • Можно интегрировать автоматическую генерацию спрайта для всех иконок с помощью svg-sprite-loader .

Для этого потребуется переопределить правило webpack по умолчанию для SVG-файлов и добавить в цепочку плагин для экспорта файлов в спрайт в файле конфигурации vue.config.js :

В использовании компонента это никак не отразится, просто внутри все ссылки будут перенаправлены на файл спрайта. И этот же файл будет кэшироваться.

На момент когда пробовал добавить это решение — сборка с этим загрузчиком падала с ошибкой и решить сразу её не удалось. Возможно что-то упустил, а возможно и баг в загрузчике.

Также можно подумать в сторону оптимизации и интеграции svgo-loader , чтобы оптимизировать SVG-файлы при сборке. Хотя можно и делать это заранее и складывать в готовом виде.

Что ещё?

Ставьте лайки, пишите комментарии что забыл, в чём неправ 🙂 Читайте русскую документацию и заходите в телеграм-чатик по Vue.

Ссылки:

  • https://svgontheweb.com/ru/
  • http://svgpocketguide.com/book/
  • https://ru.vuejs.org/v2/cookbook/editable-svg-icons.html
  • https://css-tricks.com/pretty-good-svg-icon-system/
  • https://github.com/seiyable/vue-simple-svg/
  • https://medium.com/@jackysee/simple-loading-svg-inline-in-vue-35994f5326f2
  • https://github.com/kisenka/svg-mixer/tree/master/packages/svg-transform-loader
  • https://github.com/kisenka/svg-mixer/tree/master/packages/postsvg
  • https://github.com/posthtml/posthtml-render
  • https://cli.vuejs.org/guide/webpack.html
  • https://github.com/kisenka/svg-sprite-loader
  • https://github.com/rpominov/svgo-loader
  • http://gapplin.wolfrosch.com/

Градиенты

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

Есть два типа градиентов: линейный и радиальный. Вы должны присвоить градиенту атрибут id , в противном случае на него не смогут ссылаться другие элементы внутри файла. Градиенты определяются в секции defs , а не в самой фигуре. Это позволяет их использовать многократно.

Линейный градиент (Linear Gradient)

Линейные градиенты изменяются вдоль прямой линии. Чтобы вставить градиент, нужно создать ноду внутри секции SVG файла.

Basic example

svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg"> defs> linearGradient id="Gradient1"> stop class="stop1" offset="0%" /> stop class="stop2" offset="50%" /> stop class="stop3" offset="100%" /> linearGradient> linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1"> stop offset="0%" stop-color="red" /> stop offset="50%" stop-color="black" stop-opacity="0" /> stop offset="100%" stop-color="blue" /> linearGradient> style type="text/css">  #rect1  fill: url(#Gradient1); > .stop1  stop-color: red; > .stop2  stop-color: black; stop-opacity: 0; > .stop3  stop-color: blue; > ]]> style> defs> rect id="rect1" x="10" y="10" rx="15" ry="15" width="100" height="100" /> rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)" /> svg> 

Выше находится пример линейного градиента, который применён к элементу . Внутри линейного градиента есть несколько (en-US) нод.. Эти ноды сообщают градиенту, какой цвет он должен использовать в позициях, определённых атрибутом offset для позиции и атрибутом stop-color . Это может быть задано прямо в SVG или через CSS. В целях этого примера оба метода были смешаны. Например, Gradient1 начинается с красного цвета, изменяется до прозрачно-чёрного в середине и заканчивается синим цветом. Вы можете вставить столько стоп-цветов, сколько нужно, чтобы создать смесь, которая будет красивой или ужасной, как вам нужно. Границы всегда должны изменяться от 0% (или от 0, если вы хотите опустить знак %) до 100% (или 1). Повторяющиеся значения будут использовать стоп, который будет находится дальше всех по XML-дереву. Также, подобно заливке и обводке, вы можете определить атрибут stop-opacity , чтобы задать прозрачность в этой позиции (опять же, в FF3+ можно также использовать rgba-значения для этого).

Чтобы использовать градиент, мы должны сослаться на него из атрибутов объекта fill/stroke . Это делается таким же образом, как вы ссылаетесь на элементы в CSS, используя url . В этом случае, url — это просто ссылка на наш градиент, которому задан уникальный ID, «Gradient». Чтобы добавить его, установим fill=»url(#Gradient)» . Наш объект теперь многоцветный. То же самое можно сделать с атрибутом stroke .

Элемент также принимает некоторые другие атрибуты, который определяют размер и внешний вид градиента. Направление градиента контролируется двумя точками, обозначенными атрибутами x1, x2, y1, y2 . Эти атрибуты определяют линию, вдоль которой двигается градиент. По умолчанию градиент имеет горизонтальную ориентацию, но это может быть изменено с помощью этих атрибутов. Gradient2 в примере выше предназначен для создания вертикального градиента.

Примечание: Вы также можете использовать атрибут xlink:href для градиентов. Когда он использован, атрибуты и стопы из одного градиента могут быть включены в другой. В примере выше можно было бы не пересоздавать все точки остановки в Gradient2.

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

Радиальные градиенты

Радиальные градиенты похожи на линейные, но рисуют градиент, который «излучается» из точки. Для создания градиента вам необходимо добавить элемент в секцию defs.

Basic example

svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg"> defs> radialGradient id="RadialGradient1"> stop offset="0%" stop-color="red" /> stop offset="100%" stop-color="blue" /> radialGradient> radialGradient id="RadialGradient2" cx="0.25" cy="0.25" r="0.25"> stop offset="0%" stop-color="red" /> stop offset="100%" stop-color="blue" /> radialGradient> defs> rect x="10" y="10" rx="15" ry="15" width="100" height="100" fill="url(#RadialGradient1)" /> rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#RadialGradient2)" /> svg> 

Атрибуты stop, используемые здесь — отвечают за то же, что и в линейных градиентах. Однако сейчас объект будет красным в центре и постепенно меняться к синему цвету, «двигаясь» к краям. Как и линейный градиент, элемент может иметь несколько атрибутов, описывающих его позицию и ориентацию (направленность?). Однако, в отличие от линейных градиентов, радиальные немного сложнее. Радиальные градиенты задаются двумя «точками», которые определят где будут границы. Первая «точка» определяет окружность, где градиент заканчивается. Для этого нам потребуется центр круга, который обозначается как cx и cy, и радиус — r. Изменяя эти атрибуты, вы можете «двигать» внешнюю границу градиента и менять её размер, как показано во втором прямоугольнике выше.

Вторая «точка» называется фокальной и задаётся атрибутами fx и fy. В то время как первые «точки» указывают на внешнюю границу градиента, фокальная «точка» определяет где должна быть его середина. Это легко увидеть на примере.

Center and focal point

svg width="120" height="120" version="1.1" xmlns="http://www.w3.org/2000/svg"> defs> radialGradient id="Gradient" cx="0.5" cy="0.5" r="0.5" fx="0.25" fy="0.25"> stop offset="0%" stop-color="red" /> stop offset="100%" stop-color="blue" /> radialGradient> defs> rect x="10" y="10" rx="15" ry="15" width="100" height="100" fill="url(#Gradient)" stroke="black" stroke-width="2" /> circle cx="60" cy="60" r="50" fill="transparent" stroke="white" stroke-width="2" /> circle cx="35" cy="35" r="2" fill="white" stroke="white" /> circle cx="60" cy="60" r="2" fill="white" stroke="white" /> text x="38" y="40" fill="white" font-family="sans-serif" font-size="10pt"> (fx,fy) text> text x="63" y="63" fill="white" font-family="sans-serif" font-size="10pt"> (cx,cy) text> svg> 

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

Линейный и радиальный градиенты также принимают несколько атрибутов, описывающих как они могут изменяться. Единственный атрибут, о котором я хотел бы рассказать более подробно — это spreadMethod . Этот атрибут указывает, что должно происходить, когда градиент «достигает» внешней границы градиента, но объект ещё не заполнен. Аттрибут может принимать одно и трёх значений: «pad», «reflect», или»repeat». «Pad» — это то что вы пока что видели: когда градиент достигает «краёв», финальный цвет используется для заполнения оставшейся области. «Reflect» — градиент продолжает «двигаться» в «зеркальном» отражении (стартовый цвет берётся из 100%, а конечный из 0%). А затем снова «переворачивается». И так до тех пор пока не достигнет края.

spreadMethod

svg width="220" height="220" version="1.1" xmlns="http://www.w3.org/2000/svg"> defs> radialGradient id="GradientPad" cx="0.5" cy="0.5" r="0.4" fx="0.75" fy="0.75" spreadMethod="pad"> stop offset="0%" stop-color="red" /> stop offset="100%" stop-color="blue" /> radialGradient> radialGradient id="GradientRepeat" cx="0.5" cy="0.5" r="0.4" fx="0.75" fy="0.75" spreadMethod="repeat"> stop offset="0%" stop-color="red" /> stop offset="100%" stop-color="blue" /> radialGradient> radialGradient id="GradientReflect" cx="0.5" cy="0.5" r="0.4" fx="0.75" fy="0.75" spreadMethod="reflect"> stop offset="0%" stop-color="red" /> stop offset="100%" stop-color="blue" /> radialGradient> defs> rect x="10" y="10" rx="15" ry="15" width="100" height="100" fill="url(#GradientPad)" /> rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#GradientRepeat)" /> rect x="120" y="120" rx="15" ry="15" width="100" height="100" fill="url(#GradientReflect)" /> text x="15" y="30" fill="white" font-family="sans-serif" font-size="12pt"> Pad text> text x="15" y="140" fill="white" font-family="sans-serif" font-size="12pt"> Repeat text> text x="125" y="140" fill="white" font-family="sans-serif" font-size="12pt"> Reflect text> svg> 

У обоих типов градиентов также есть атрибут gradientUnits , который описывает систему измерений, которую вы собираетесь использовать, когда описываете размеры или ориентацию или градиент. Данный атрибут принимает 2 возможных значения: userSpaceOnUse или objectBoundingBox (дефолтное, показывалось во всех примерах выше). objectBoundingBox автоматически адаптирует градиент к размеру объекта, так что вы можете указать координаты в виде значений от 0 до 1, и браузер автоматически их отпозиционирует. userSpaceOnUse позиционирует градиент в абсолютных единицах измерения, так что вам необходимо знать где находится целевой объект, чтобы правильно применить к нему градиент. radialGradient выше может быть переписан:

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

Существуют и другие предостережения для работы с gradientUnits=»objectBoundingBox» , когда поле ограничения объекта не является квадратным, но они довольно сложны и им придётся ждать, пока кто-то другой не соизволит объяснить их.

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

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 6 авг. 2023 г. by MDN contributors.

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

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