1. Прежде чем начать
Анимация, управляемая прокруткой, позволяет контролировать воспроизведение анимации в зависимости от положения элемента в контейнере прокрутки. Это означает, что при прокрутке вверх или вниз анимация будет перемещаться вперед или назад. Кроме того, с помощью анимации, управляемой прокруткой, вы также можете управлять анимацией в зависимости от положения элемента внутри его контейнера прокрутки. Это позволяет создавать интересные эффекты, такие как параллаксное фоновое изображение, индикаторы выполнения прокрутки и изображения, которые появляются по мере приближения к экрану.
В Chrome 115 появилась поддержка набора классов JavaScript и свойств CSS, позволяющих легко создавать декларативные анимации, управляемые прокруткой. Эти новые API работают совместно с существующими API веб-анимаций и CSS-анимаций.
В этом практическом занятии вы научитесь создавать анимации, управляемые прокруткой, с помощью CSS. Пройдя это занятие, вы познакомитесь со многими новыми свойствами CSS, появившимися благодаря этой замечательной функции, такими как scroll-timeline , view-timeline , animation-timeline и animation-range .
Что вы узнаете
- Как создать эффект параллаксного фона с помощью прокручиваемой временной шкалы в CSS.
- Как создать индикатор выполнения с прокручиваемой временной шкалой в CSS.
- Как создать эффект появления изображения с помощью элемента View Timeline в CSS.
- Как задать различные диапазоны значений на временной шкале представления в CSS.
Что вам понадобится
Одна из следующих комбинаций устройств:
- Для работы требуется последняя версия Chrome (115 или более поздняя) на ChromeOS, macOS или Windows с включенным флагом "Experimental Web Platform Features".
- Базовое понимание HTML
- Фундаментальное понимание CSS, в частности анимации в CSS.
2. Настройка
Все необходимое для этого проекта доступно в репозитории GitHub. Для начала клонируйте код и откройте его в вашей любимой среде разработки.
- Откройте новую вкладку браузера и перейдите по ссылке https://github.com/googlechromelabs/io23-scroll-driven-animations-codelab .
- Клонируйте репозиторий.
- Откройте код в предпочитаемой вами IDE.
- Для установки зависимостей выполните
npm install. - Запустите команду
npm startи перейдите по адресу http://localhost:3000/ . - В качестве альтернативы, если у вас не установлен npm, откройте файл
src/index.htmlв Chrome.
3. Изучите временные рамки анимации.
По умолчанию анимация, прикрепленная к элементу, воспроизводится на временной шкале документа. Это означает, что при загрузке страницы анимация отсчитывает время вперед. Это временная шкала анимации по умолчанию, и до настоящего момента это была единственная доступная вам временная шкала анимации.
Благодаря анимации, управляемой прокруткой, вы получаете доступ к двум новым типам временных шкал:
- Хронология прогресса прокрутки
- Просмотреть хронологию прогресса
В CSS эти временные шкалы можно прикрепить к анимации с помощью свойства animation-timeline . Давайте посмотрим, что означают эти новые временные шкалы и чем они отличаются друг от друга.
Хронология прогресса прокрутки
Шкала прогресса прокрутки — это шкала анимации, которая связана с прогрессом в положении прокрутки контейнера прокрутки (также называемого областью прокрутки или скроллером) вдоль определенной оси. Она преобразует положение в диапазоне прокрутки в процент прогресса вдоль временной шкалы.
Начальная позиция прокрутки соответствует 0% прогресса, а конечная — 100% прогресса. На приведенной ниже визуализации обратите внимание, что прогресс увеличивается от 0% до 100% по мере прокрутки вниз.
Просмотреть хронологию прогресса
Этот тип временной шкалы связан с относительным продвижением определенного элемента внутри контейнера прокрутки. Как и в случае с временной шкалой прогресса прокрутки, отслеживается смещение прокрутки в скроллере. В отличие от временной шкалы прогресса прокрутки, именно относительное положение объекта внутри скроллера определяет прогресс. Это сравнимо с IntersectionObserver , который отслеживает, насколько элемент виден в скроллере. Если элемент не виден в скроллере, он не пересекается. Если он виден внутри скроллера — даже в самой маленькой части — он пересекается.
Отображение прогресса начинается с момента, когда объект начинает пересекать полосу прокрутки, и заканчивается, когда объект перестает пересекать полосу прокрутки. На следующей визуализации обратите внимание, что отсчет прогресса начинается с 0%, когда объект входит в контейнер прокрутки, и достигает 100% к моменту, когда он покидает контейнер прокрутки.
По умолчанию анимация, связанная с временной шкалой прогресса просмотра, применяется ко всему ее диапазону. Она начинается с момента, когда объект входит в область прокрутки, и заканчивается, когда объект покидает область прокрутки.
Также можно привязать его к определенной части временной шкалы прогресса просмотра, указав диапазон, к которому он должен быть привязан. Например, это может быть только момент, когда объект входит в область прокрутки. На следующей визуализации прогресс начинает отсчет с 0%, когда объект входит в контейнер прокрутки, но достигает 100% уже с момента полного пересечения с ним.
Возможные диапазоны временной шкалы просмотра, на которые вы можете нацелиться, это: cover , contain , entry , exit , entry-crossing и exit-crossing . Эти диапазоны объясняются далее в этом практическом руководстве, но если вы не хотите ждать, воспользуйтесь инструментом, расположенным по адресу https://goo.gle/view-timeline-range-tool, чтобы увидеть, что представляет собой каждый диапазон.
4. Создайте эффект параллаксного фона.
Первый эффект, который нужно добавить на страницу, — это эффект параллакса на основном фоновом изображении. При прокрутке страницы вниз фоновое изображение должно двигаться, хотя и с разной скоростью. Для этого используется временная шкала прогресса прокрутки.
Для реализации этого необходимо выполнить два шага:
- Создайте анимацию, которая изменяет положение фонового изображения.
- Свяжите анимацию с процессом прокрутки документа.
Создайте анимацию
- Для создания анимации используйте стандартный набор ключевых кадров. В нём переместите положение фона от 0% по вертикали до 100%:
src/styles.css
@keyframes move-background {
from {
background-position: 50% 0%;
}
to {
background-position: 50% 100%;
}
}
- Теперь прикрепите эти ключевые кадры к элементу body:
src/styles.css
body {
animation: 1s linear move-background;
}
С помощью этого кода к элементу body добавляется анимация move-background . Свойство animation-duration устанавливается на одну секунду, и используется linear сглаживание.
Свяжите анимацию с прогрессом прокрутки корневого элемента, используя анонимную временную шкалу прогресса прокрутки.
Самый простой способ создать временную шкалу прогресса прокрутки — использовать функцию scroll() . Она создаст анонимную временную шкалу прогресса прокрутки, значение которой можно задать в свойстве animation-timeline .
Функция scroll() принимает аргументы <scroller> и <axis> .
Допустимые значения для аргумента <scroller> следующие:
-
nearest. Использует ближайший родительский контейнер прокрутки (по умолчанию). -
root. Использует область просмотра документа в качестве контейнера прокрутки. -
self. Использует сам элемент в качестве контейнера прокрутки.
Допустимые значения для аргумента <axis> следующие:
-
block. Использует скорость продвижения вдоль оси блока контейнера прокрутки (по умолчанию). -
inline. Использует показатель прогресса вдоль оси прокрутки контейнера. -
y. Использует показатель прогресса вдоль оси Y контейнера прокрутки. -
x. Использует показатель прогресса вдоль оси x контейнера прокрутки.
Для привязки анимации к корневому скроллеру по оси блока значения, передаваемые в функцию scroll() — это root и block . В совокупности это значение будет scroll(root block) .
- Установите значение свойства
animation-timelineдля элемента body в качестве параметраscroll(root block). - Кроме того, поскольку
animation-durationвыраженная в секундах, не имеет смысла, установите значениеauto. Если вы не укажетеanimation-duration, по умолчанию будет установлено значениеauto.
src/styles.css
body {
animation: linear move-background;
animation-duration: auto;
animation-timeline: scroll(root block);
}
Поскольку корневой скроллер также является ближайшим родительским скроллером для элемента body, вы также можете использовать значение nearest :
src/styles.css
body {
animation: linear move-background;
animation-duration: auto;
animation-timeline: scroll(nearest block);
}
Поскольку nearest и block являются значениями по умолчанию, вы можете даже их опустить. В этом случае код можно упростить до следующего вида:
src/styles.css
body {
animation: linear move-background;
animation-duration: auto;
animation-timeline: scroll();
}
Проверьте внесенные изменения.
Если всё прошло успешно, у вас должно получиться следующее:
В противном случае, посмотрите ветку кода solution-step-1 .
5. Создайте индикатор выполнения для галереи изображений.
На странице находится горизонтальная карусель, для отображения которой необходима полоса прогресса.
Разметка для карусели выглядит следующим образом:
src/index.html
<div class="gallery">
<div class="gallery__scrollcontainer" style="--num-images: 3;">
<div class="gallery__progress"></div>
<div class="gallery__entry">
...
</div>
<div class="gallery__entry">
...
</div>
<div class="gallery__entry">
...
</div>
</div>
</div>
Ключевые кадры для индикатора выполнения уже созданы и выглядят следующим образом:
src/styles.css
@keyframes adjust-progress {
from {
transform: scaleX(calc(1 / var(--num-images)));
}
to {
transform: scaleX(1);
}
}
Эту анимацию необходимо прикрепить к элементу ` gallery__progress с помощью временной шкалы прогресса прокрутки. Как показано на предыдущем шаге, этого можно добиться, создав анонимную временную шкалу прогресса прокрутки с помощью функции scroll() :
src/styles.css
.gallery__progress {
animation: linear adjust-progress;
animation-duration: auto;
animation-timeline: scroll(nearest inline);
}
Хотя этот фрагмент кода может показаться рабочим, на самом деле это не так из-за особенностей автоматического поиска контейнера прокрутки с помощью метода ` nearest . При поиске ближайшего элемента прокрутки учитываются только те элементы, которые могут повлиять на его положение. Поскольку .gallery__progress имеет абсолютное позиционирование, первым родительским элементом, определяющим его положение, является элемент ` .gallery , поскольку к нему применено position: relative . Это означает, что элемент ` .gallery__scrollcontainer — именно тот элемент прокрутки, который необходимо найти, — вообще не учитывается при этом автоматическом поиске.
Чтобы обойти эту проблему, создайте именованную временную шкалу прогресса прокрутки для элемента .gallery__scrollcontainer и свяжите с ней элемент .gallery__progress , используя это имя.
Создайте и свяжите именованную временную шкалу прогресса прокрутки.
Чтобы создать именованную временную шкалу прогресса прокрутки для элемента, установите свойство CSS scroll-timeline-name контейнера прокрутки на любое желаемое значение. Значение должно начинаться с -- .
Поскольку галерея прокручивается по горизонтали, вам также необходимо установить свойство scroll-timeline-axis . Допустимые значения совпадают с аргументом <axis> функции scroll() .
Наконец, чтобы связать анимацию с временной шкалой прогресса прокрутки, установите свойство animation-timeline элемента, который необходимо анимировать, на то же значение, что и идентификатор, используемый для scroll-timeline-name .
- Измените файл
styles.css, добавив в него следующее:
src/styles.css
.gallery__scrollcontainer {
/* Create the gallery-is-scrolling timeline */
scroll-timeline-name: --gallery-is-scrolling;
scroll-timeline-axis: inline;
}
.gallery__progress {
animation: linear adjust-progress;
animation-duration: auto;
/* Set gallery-is-scrolling as the timeline */
animation-timeline: --gallery-is-scrolling;
}
Проверьте внесенные изменения.
Если всё прошло успешно, у вас должно получиться следующее:
В противном случае, посмотрите ветку кода solution-step-2 .
6. Анимируйте изображения в галерее при их появлении и исчезновении из области прокрутки.
Плавное появление изображений в галерее
Настройте анонимный просмотр графика выполнения работ.
Интересный эффект — плавное появление изображений в галерее по мере их появления. Для этого можно использовать функцию «Просмотр временной шкалы».
Для создания временной шкалы прогресса можно использовать функцию view() . Ее принимаемые аргументы: <axis> и <view-timeline-inset> .
- Параметр
<axis>аналогичен параметру на временной шкале прогресса прокрутки и определяет, какую ось отслеживать. - С помощью
<view-timeline-inset>` можно указать смещение (положительное или отрицательное), чтобы корректировать границы элемента в зависимости от того, находится ли он в поле зрения или нет.
- Ключевые кадры уже созданы, поэтому вам нужно только их прикрепить. Для этого создайте шкалу прогресса просмотра для каждого элемента
.gallery__entry.
src/styles.css
@keyframes animate-in {
from {
opacity: 0;
clip-path: inset(50% 0% 50% 0%);
}
to {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
}
.gallery__entry {
animation: linear animate-in;
animation-duration: auto;
animation-timeline: view(inline);
}
Ограничить диапазон отображения временной шкалы хода выполнения.
Если сохранить CSS-код и загрузить страницу, вы увидите, как элементы плавно появляются, но что-то кажется не так. Их прозрачность равна 0 , когда они полностью исчезают из поля зрения, и достигает 1 только после полного исчезновения.
Это связано с тем, что диапазон по умолчанию для отображения временной шкалы хода выполнения — полный диапазон. Он называется диапазоном cover .
- Чтобы ограничить область действия анимации только определенным диапазоном
entryобъекта, используйте свойство CSS `animation-range, чтобы установить ограничение на время запуска анимации.
src/styles.css
.gallery__entry {
animation: linear fade-in;
animation-duration: auto;
animation-timeline: view(inline);
animation-range: entry 0% entry 100%;
}
Теперь анимация начинается с entry 0% (объект вот-вот войдет в полосу прокрутки) и entry 100% (объект полностью вошел в полосу прокрутки).
Возможные диапазоны временной шкалы просмотра следующие:
-
cover. Отображает полный диапазон временной шкалы прогресса просмотра. -
entry. Представляет собой диапазон, в течение которого основной блок входит в зону видимости индикатора выполнения. -
exit. Представляет собой диапазон, в течение которого основной блок выходит за пределы видимой области отображения прогресса. -
entry-crossing. Обозначает диапазон, в течение которого основной прямоугольник пересекает край конечной границы. -
exit-crossing. Обозначает диапазон, в течение которого основной прямоугольник пересекает начальную границу. -
contain. Представляет диапазон, в течение которого основной блок либо полностью содержится в пределах области видимости индикатора выполнения, либо полностью закрывает ее. Это зависит от того, выше или ниже объект, чем полоса прокрутки.
Воспользуйтесь инструментом, расположенным по адресу https://goo.gle/view-timeline-range-tool, чтобы увидеть, что представляет собой каждый диапазон и как проценты влияют на начальную и конечную позиции.
- Поскольку начальный и конечный диапазоны здесь одинаковы, и используются смещения по умолчанию, упростите имя
animation-rangeдо одного имени диапазона анимации:
src/styles.css
.gallery__entry {
animation: linear animate-in;
animation-duration: auto;
animation-timeline: view(inline);
animation-range: entry;
}
Постепенно исчезают изображения в галерее
- Чтобы изображения плавно исчезали при выходе из зоны прокрутки, можно использовать тот же подход, что и для анимации появления, но выбрать другой диапазон.
src/styles.css
@keyframes animate-out {
from {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
to {
opacity: 0;
clip-path: inset(50% 0% 50% 0%);
}
}
.gallery__entry {
animation: linear animate-in, linear animate-out;
animation-duration: auto;
animation-timeline: view(inline);
animation-range: entry, exit;
}
Ключевые кадры animate-in будут применены к диапазону entry , а ключевые кадры animate-out к диапазону exit .
Проверьте внесенные изменения.
Если всё прошло успешно, у вас должно получиться следующее:
В противном случае, посмотрите ветку кода solution-step-3 .
7. Анимируйте изображения галереи при их появлении и исчезновении из области прокрутки, используя один набор ключевых кадров.
Аргументы в пользу одного набора ключевых кадров
Вместо того чтобы прикреплять две анимации к разным диапазонам, можно создать один набор ключевых кадров, который уже содержит информацию о диапазоне.
Форма ключевых кадров выглядит следующим образом:
@keyframes keyframes-name {
range-name range-offset {
...
}
range-name range-offset {
...
}
}
- Объедините ключевые кадры появления и исчезновения следующим образом:
src/styles.css
@keyframes animate-in-and-out {
entry 0% {
opacity: 0;
clip-path: inset(50% 0% 50% 0%);
}
entry 90% {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
exit 10% {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
exit 100% {
opacity: 0;
clip-path: inset(50% 0% 50% 0%);
}
}
- Если информация о диапазоне присутствует в ключевых кадрах, вам больше не нужно указывать
animation-rangeотдельно. Прикрепите ключевые кадры в качестве свойстваanimation.
src/styles.css
.gallery__entry {
animation: linear animate-in-and-out both;
animation-duration: auto;
animation-timeline: view(inline);
}
Проверьте внесенные изменения.
Если все прошло успешно, вы должны получить тот же результат, что и на предыдущем шаге. В противном случае, проверьте ветку кода solution-step-4 .
8. Поздравляем!
Вы завершили этот практический урок и теперь знаете, как создавать временные шкалы прогресса прокрутки и отображения в CSS!
Узнать больше
Ресурсы: