CSS-анимации для ротации изображений
В процессе экспериментов с анимированными SVG-масками, мне пришлось как следует разобраться с алгоритмами CSS-анимаций.
Например, в этом демо используется две анимации: одна для маски, вторая — для смены изображений. Сейчас речь пойдет о второй (и её вариантах).
Такая анимация нужна, чтобы последовательно показывать и скрывать картинки, в то время, когда эффект их появления обеспечивается другой анимацией.
При использовании HTML-элементов это можно было бы сделать одной анимацией, но при использовании SVG-масок для всех элементов ротации используется одна маска, и ей нельзя задать задержку воспроизведения в зависимости от позиции элемента, к которому она применилась. Есть два решения: создавать для каждого шага по маске с нужной задержкой воспроизведения или просто скрывать элементы, которые не нужны в данный момент. Я выбрала второй вариант.
Мне не хотелось использовать JS, потому что простую анимацию можно сделать средствами CSS. Кроме того, использование переменных в SCSS позволяет легко синхронизировать между собой анимации масок и смены изображений.
Итак, первый вариант анимации.
Задача: сделать алгоритм последовательной смены произвольного количества изображений. Одно изображение должно сменять другое без плавных переходов. В один момент времени показывается одна картинка.
Вот как это должно работать:
See the Pen kDpsG by yoksel (@yoksel) on CodePen.
Делаем разметку галереи:
В демо я добавила картинки фоном, но внутри элементов галереи может быть любое содержимое. Для демонстрации SVG-масок структура галереи переносится, соответственно, в SVG.
Добавляем SCSS:
Теперь самое интересное: анимация. Создаем конфиг:
Нужно понимать как работает последний параметр. Для всех элементов задается одна и та же анимация: картинка показывается на короткий промежуток времени, и затем скрывается. Переменная $step-perc
используется в коде анимации, и определяет как долго будет отображаться каждая картинка:
Например, в галерее из четырех элементов каждая картинка будет показываться 25% времени, а в остальное время будет скрыта.
Задаем анимацию элементам галереи:
Элементы исчезают и появляются одновременно, нужно добавить каждому из них задержку воспроизведения:
Первому элементу задержка не нужна, для остальных рассчитываем задержку, умножая длительность одного шага на позицию элемента минус 1. То есть второй элемент начнет воспроизводиться на шаг позже, третий — на два шага позже, и так далее.
Очевидно, что animation-delay
будет удобнее рассчитывать в цикле:
Кроме того, так не придется каждый раз дописывать или убирать задержку шагов, если их число изменится.
Вот что получается в итоге:
See the Pen hzlnj by yoksel (@yoksel) on CodePen.
Можно отредактировать заготовку, сделав простую ротацию:
See the Pen kpoiq by yoksel (@yoksel) on CodePen.
А можно добавить спецэффектов с помощью анимированных SVG-масок, например:
See the Pen kJwCb by yoksel (@yoksel) on CodePen.
Для этого демо структура галереи была перенесена в SVG.
Второй вариант анимации.
Задача: картинки появляются по очереди от нижних слоев к верхним, при этом одновременно видны две картинки: текущая и предыдущая под ней, это позволит используя маски сделать "перетекание" из одной картинки в другую.
Как это должно работать:
See the Pen KrqHC by yoksel (@yoksel) on CodePen.
Анимация делается по тем же принципам, что и предыдущая, но имеет свои особенности.
Во-первых, под самым первым слоем тоже должно что-то быть, для этого немного меняем разметку и добавляем "дно":
Оно не участвует в ротации, а просто всегда там лежит. Изображение в этом слое должно быть таким же как в последнем слое, это позволит зациклить анимацию.
Во-вторых, чтобы каждый слой успевал послужить подложкой для следующего, удлиняем время показа каждого слоя, теперь оно равно двум шагам:
В течение первого шага слой появляется сам, а в течение второго служит фоном для следующего слоя.
Во-третьих, самому верхнему слою потребуется своя отдельная анимация.
Почему?
Как уже говорилось выше, в этом варианте анимации каждый слой показывается по времени два шага.
Последний слой изначально тоже показывается два шага, но он самый верхний, и не может служить подложкой другим слоям (над ним ничего нет). Следовательно, его нужно показывать по времени один шаг, а затем скрыть. При этом самый нижний слой является копией верхнего, так что если по прошествии одного шага скрыть самый верхний слой, под ним покажется точно такой же нижний, и анимация аккуратно зациклится.
Делаем переменную с половинной длительностью анимации:
Дублируем анимацию с новой длительностью:
Переопределяем анимацию для последнего шага:
Визуально результат практически не отличается от предыдущего варианта:
See the Pen rJogH by yoksel (@yoksel) on CodePen.
Но если к элементам галереи применить SVG-маски, получается интересное:
See the Pen Simple animated mask in SVG (rhomb) by yoksel (@yoksel) on CodePen.
Синхронизация слоёных анимаций не самая простая задача, но результат того стоит.
Уверена, что на основе таких анимаций можно придумать интересные визуальные эффекты, а понимание принципа их работы может сэкономить временя при необходимости сделать что-то подобное.
- Ссылки по теме:
- Css Animation
- Анимированные SVG-маски
- Метки:
- анимация