Главная » Статьи » Scroll-linked и ScrollTimeline анимация

Scroll-linked и ScrollTimeline анимация

Scroll-linked и ScrollTimeline анимация

От автора: спецификация Scroll-linked Animations — это предстоящее и экспериментальное дополнение, которое позволяет нам связывать анимацию с прокруткой: когда вы прокручиваете вверх и вниз контейнер прокрутки, связанный элемент также продвигается или перематывается соответственно.

Мы рассмотрели некоторые варианты использования в предыдущем разделе, посвященном CSS-трюкам, все они управляются правилом CSS @scroll-timeline и свойством animation-timeline, эти варианты использования были созданы с использованием только HTML и CSS. Без JavaScript.

Помимо интерфейса CSS, который мы получаем со спецификацией scroll-connected Animations, в ней также описан интерфейс JavaScript для реализации scroll-linked анимаций. Давайте рассмотрим класс ScrollTimeline и то, как его использовать с API веб-анимации.

API веб-анимации: краткое резюме

API веб-анимации (WAAPI) уже рассматривался в CSS-Tricks. Вкратце, этот API позволяет нам создавать анимации и управлять их воспроизведением с помощью JavaScript. Возьмем, к примеру, следующую CSS-анимацию, в которой полоса находится вверху страницы, и:

Изменяет цвет от красного до темно-красного

Изменяет ширину от нуля до полной ширины контейнера (путем масштабирования оси x).

При переводе анимации CSS в ее аналог WAAPI код становится следующим:

new Animation( new KeyframeEffect( document.querySelector('.progressbar'), { backgroundColor: ['red', 'darkred'], transform: ['scaleX(0)', 'scaleX(1)'], }, { duration: 2500, fill: 'forwards', easing: 'linear', } )
).play();

Или, в качестве альтернативы, используйте более краткий синтаксис с использованием Element.animate():

document.querySelector('.progressbar').animate( { backgroundColor: ['red', 'darkred'], transform: ['scaleX(0)', 'scaleX(1)'], }, { duration: 2500, fill: 'forwards', easing: 'linear', }
);

В двух последних примерах мы можем выделить две вещи. Во-первых — объект, описывающий, какие свойства нужно анимировать:

{ backgroundColor: ['red', 'darkred'], transform: ['scaleX(0)', 'scaleX(1)'],
}

Во-вторых – объект, который настраивает продолжительность анимации, замедление и т. д.:

{ duration: 2500, fill: 'forwards', easing: 'linear',
}

Создание и прикрепление шкалы времени прокрутки

Чтобы анимация управлялась с помощью прокрутки, мы можем сохранить существующий код WAAPI, но необходимо расширить его, добавив к нему экземпляр класса ScrollTimeline.

Класс ScrollTimeline позволяет нам описывать AnimationTimeline, чьи значения времени определяются не продолжительностью времени, а прогрессом прокрутки в контейнере прокрутки. Его можно настроить с помощью нескольких опций:

source: Прокручиваемый элемент, прокрутка которого запускает активацию и управляет прогрессом временной шкалы. По умолчанию это document.scrollingElement (т. е. Контейнер прокрутки, который прокручивает весь документ).

orientation: Определяет направление прокрутки, которое запускает активацию и управляет прогрессом временной шкалы. По умолчанию равно vertical.

scrollOffsets: Значения, которые определяет эффективное смещение прокрутки, перемещаясь в направлении, указанном в свойстве orientation. Они представляют собой равноудаленные по ходу выполнения интервалы, в которых активна временная шкала.

Эти параметры передаются в конструктор. Например:

const myScrollTimeline = new ScrollTimeline({ source: document.scrollingElement, orientation: 'block', scrollOffsets: [ new CSSUnitValue(0, 'percent'), new CSSUnitValue(100, 'percent'), ],
});

Не случайно эти параметры в точности совпадают с дескрипторами CSS @scroll-timeline. Оба подхода позволяют достичь одного и того же результата, разница лишь в использовании языка для их определения.

Чтобы добавить вновь созданный экземпляр ScrollTimeline к анимации, мы передаем его в качестве второго аргумента в конструктор Animation:

new Animation( new KeyframeEffect( document.querySelector('#progress'), { transform: ['scaleX(0)', 'scaleX(1)'], }, { duration: 1, fill: 'forwards' } ), myScrollTimeline
).play();

При использовании синтаксиса Element.animate() установите его как параметр timeline:

document.querySelector("#progress").animate( { transform: ["scaleX(0)", "scaleX(1)"] }, { duration: 1, fill: "forwards", timeline: myScrollTimeline }
);

С этим кодом анимация управляется нашим экземпляром ScrollTimelin, а не DocumentTimeline. Текущая экспериментальная реализация в Chromium использует scrollSource вместо source. Вот почему вы видите и source и scrollSource в примерах кода.

Несколько слов о совместимости браузеров

На момент написания статьи только браузер Chromium поддерживает класс ScrollTimeline. К счастью, есть полифил Scroll-Timeline от Роберта Флэка, который мы можем использовать для заполнения неподдерживаемых пробелов во всех других браузерах. Фактически, все демонстрации в этой статье, включают его.

Полифилл доступен в виде модуля и регистрирует себя, если поддержка не обнаружена. Чтобы включить его, добавьте в секцию import своего кода следующий оператор:

import 'https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js';

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

Продвинутая временная шкала прокрутки

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

Смещение на основе элементов состоит из трех частей:

target: Отслеживаемый элемент DOM.

edge: То, за чем наблюдает ScrollTimeline.

threshold: Число в диапазоне от 0.0 до 1.0 которое указывает, какая часть target видна в области прокрутки edge.

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

{ target: document.querySelector('#targetEl'), edge: 'end', threshold: 0.5,
}

Обычно в свойство scrollOffsets передаются два из этих объектов.

const $image = document.querySelector('#myImage'); $image.animate( { opacity: [0, 1], clipPath: ['inset(45% 20% 45% 20%)', 'inset(0% 0% 0% 0%)'], }, { duration: 1, fill: "both", timeline: new ScrollTimeline({ scrollSource: document.scrollingElement, timeRange: 1, fill: "both", scrollOffsets: [ { target: $image, edge: 'end', threshold: 0.5 }, { target: $image, edge: 'end', threshold: 1 }, ], }), }
);

Вот еще несколько примеров, которые я приготовил.

Секция горизонтальной прокрутки

Пример основан на демонстрации Кэмерона Найта, в которой есть секция горизонтальной прокрутки. Она ведет себя аналогично, но использует ScrollTimeline вместо GSAP ScrollTrigger.

CoverFlow

Помните CoverFlow из iTunes? Что ж, вот версия, построенная на ScrollTimeline:

Эта демонстрация не работает должным образом в Chromium из-за ошибки. Проблема в том, что начальная и конечная позиции рассчитываются неправильно.

CSS или JavaScript?

Нет никакой реальной разницы в использовании CSS или JavaScript для Scroll-linked анимаций, за исключением используемого языка: оба используют одни и те же концепции и конструкции. В духе прогрессивного улучшения я бы выбрал CSS для такого рода эффектов.

Однако, как мы уже говорили ранее, поддержка реализации на основе CSS на момент написания статьи была довольно слабой:

Chromium имеет только экспериментальную реализацию.

Firefox только готовится для внедрения реализации на основе CSS.

Никаких сообщений от Safari пока нет.

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

Автор: Bramus

Источник: css-tricks.com

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен