SVG-прелоадеры
В поисках что бы ещё такого сделать чтобы ездило, я захотела сделать прелоадеры на SVG.
Получилось здорово, хотя результат пока не сильно подходит для использования в реальной жизни.
Вот такие прелоадеры у меня получились:
See the Pen Thinking about SVG-preloaders by yoksel (@yoksel) on CodePen.
Они могут быть использованы на любом фоне. Элементы в них могут менять не только прозрачность, но и цвет, обводку или положение в пространстве. Можно придумать огромное количество разных вариантов оформления и анимации.
Более того, использование символов позволяет как угодно менять элементы прелоадеров (сами прелоадеры, к слову, вовсе не обязательно должны быть круглыми):
See the Pen Changing items of SVG-preloaders, .v2 by yoksel (@yoksel) on CodePen.
Вместо кружочков можно вставить любые фигуры: рыбок, цветочки, снежинки, котиков... Вид прелоадера можно менять по сезону, под настроение или вовсе случайным образом.
Как сделать простой прелоадер?
Как ни странно, его можно просто написать руками, не заходя в графический редактор. Первым делом нам потребуется кружочек, напишем его:
Простая фигура без оформления, оно потом будет задано через CSS.
Чтобы явно обозначить переиспользуемый элемент, завернем его в symbol
:
Теперь на страницу нужно добавить нужное количество копий символа. Копии вставляются через use
:
Чтобы иметь возможность манипулировать всеми копиями одновременно, завернем их в тег g
:
Это пригодится если всей группе сразу надо будет добавить общие стили оформления или прелоадер надо будет как-то трансформировать: уменьшить, подвинуть и так далее.
Мой код в итоге выглядит вот так:
Внутри тега SVG объявлен символ и ниже группа, содержащая его копии.
Обратите внимание на viewBox
:
Этот атрибут показывает размеры отображаемой области SVG-содержимого.
Совершенно необходимая вещь, если вы ещё не решили какого размера должен быть ваш прелоадер: если элементу с viewBox
задать ширину и высоту, содержимое изображения растянется или сожмется под заданные размеры.
Результат кода на странице выглядит вот так:
See the Pen ozKmy by yoksel (@yoksel) on CodePen.
Всё верно, кружочки имеют заливку по умолчанию (черным цветом) и им не задано положение в пространстве, поэтому они скопились в левом верхнем углу области, размеры которой заданы viewBox
.
Серые границы отображаемой области добавила для понятности, на самом деле границ viewBox
не видно. Кстати, границы удобно делать с помощью такой фигуры:
В CSS:
Такой прямоугольник растянется на всю отображаемую область и покажет её границы. Отображаемая область может не совпадать с границами самого SVG-элемента.
Теперь к копиям символа нужно добавить стили.
Я использую SCSS, потому что это проще, быстрее, и в нем можно использовать циклы и переменные. Например, прелоадер может иметь свой конфиг:
Используем переменные, чтобы задать размеры прелоадера и цвет фигур:
Результат:
See the Pen rAwgq by yoksel (@yoksel) on CodePen.
Будущий прелоадер получил заданные размеры, кружки стали оранжевыми, но всё ещё находятся в левом верхнем углу. Нужна трансформация.
Первым делом нужно задать центр трансформации, потому что в SVG он по умолчанию находится в левом верхнем углу родительского элемента. Если к родителю не применялись трансформации, центр вращения окажется в левом верхнем углу отображаемой области.
Координаты центра находим разделив на два ширину и высоту:
Теперь с помощью транформации надо расположить кружки по кругу. У каждого кружка свой угол поворота, поэтому трансформация задается с помощью цикла @for
и селектора :nth-child
.
Сама трансформация состоит из трех частей:
Весь код трансформаций:
translate(10px, 10px)
можно было бы убрать из CSS и добавить символу, но удобнее хранить все трансформации в одном месте.
Также было бы удобно задавать translate(10px, 10px) scale(.85)
не каждому отдельному кружку, а классу .u-circle
, но, к сожалению, трансформации нельзя склеивать. То есть нельзя трансформировать элемент, а потом трансформировать его ещё раз — так не получится, потому что вторая трансформация перезапишет первую (можно сделать только некое подобие склейки, мы рассмотрим этот способ ниже, для варианта, когда склейка становится острой необходимостью).
Результат трансформаций:
See the Pen KBtme by yoksel (@yoksel) on CodePen.
Все кружки послушно расположились по кругу.
Теперь анимируем. Создаем ключевые кадры:
Добавляем анимацию в элемент:
Эта анимация сделает так, чтобы все символы исчезали и появлялись одновременно. Чтобы сделать анимацию "бегущей", каждому кружку нужно задать свою задержку анимации. Для этого воспользуемся циклом с трансформациями, который у нас уже есть, и допишем в него animation-delay
:
Результат:
See the Pen Jgixz by yoksel (@yoksel) on CodePen.
Но что если мы хотим анимировать не только прозрачность заливки, но и цвет символов?
Добавляем ключевые кадры с изменением цвета:
Можно было бы добавить управление цветами в предыдущую анимацию, но так мы можем более гибко менять обе анимации, при этом изменения в одной анимации не будут затрагивать другую. Кроме того, для разных анимаций можно задать разные параметры воспроизведения, чтоб иногда может быть полезно.
Добавляем вторую анимацию:
See the Pen nFqzd by yoksel (@yoksel) on CodePen.
На этом можно было бы и остановиться, но что если символы будут помимо цвета и прозрачности менять свое положение в пространстве?
Пишем ключевые кадры с простой анимацией:
Добавляем новую анимацию в список:
И на выходе получаем нечто интересное:
See the Pen JDHzK by yoksel (@yoksel) on CodePen.
Таки да: трансформации не склеиваются, поэтому где-то на середине символ возвращается в первоначальное положение, уменьшается там вдвое (потому что transform: scale(.5)
), а потом летит себе дальше. Так происходит потому, что трансформация, задающая положение каждого отдельного символа, перезаписывавется трансформацией, заданной в анимации.
Как сохранить положение символа на плоскости и при этом иметь возможность дополнительно его масштабировать?
Можно суммировать трансформации родительских и дочерних элементов. Это увеличит разметку, но даст больше возможностей в анимации. Заворачиваем каждый символ в группу:
Переносим трансформацию элементов с use
на группу и убираем анимацию transform
:
Всё работает:
See the Pen nbird by yoksel (@yoksel) on CodePen.
А теперь пробуем добавить анимацию с трансформацией. На этот раз не группе, а символам:
See the Pen hDyqc by yoksel (@yoksel) on CodePen.
Получилось, кружочки никуда не улетают, но теперь им не хватает задержки анимации. Для этого нам опять понадобятся цикл и :nth-child
, но цикл будет идти по группам (а не по символам), потому что символы находятся каждый в своей группе:
Результат:
See the Pen Fqwpm by yoksel (@yoksel) on CodePen.
Таким образом усложнив разметку можно получить более сложные и интересные варианты анимированных трнасформаций. К символам можно добавлять две и больше трансформации без опасений что что-то поломается:
See the Pen lGLni by yoksel (@yoksel) on CodePen.
Заменить кружочки на что-то другое можно просто поменяв символ:
See the Pen bEIuo by yoksel (@yoksel) on CodePen.
Получился некий конструктор, в котором можно легко менять вид и анимации прелоадера, а сам прелоадер может быть сколь угодно разным, и вовсе не обязательно в форме кольца.
Было бы волшебно, если бы вся эта красота просто везде работала, но всё не так просто. IE9-11 вообще не поддерживают CSS-анимации и CSS-трансформации, задаваемые SVG-элементам, то есть в них кружочки так и останутся лежать стопкой в левом верхнем углу, как в этом примере. Ещё предполагаю, что могут быть проблемы с производительностью на слабых устройствах.
Мне понравились результаты экспериментов, хотя если бы трансформы можно было складывать — код был бы изящней. Также хотелось бы более равномерной поддержки браузерами. Для широкого использования такие прелоадеры, по-моему, пока не готовы, но наверняка их можно использовать на промо-сайтах, как небольшое эффектное дополнение.
- Метки:
- SVG,
- эксперименты