Анимация при прокрутке страницы

Принцип scroll-driven анимаций

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

  • позиция скролла → прогресс анимации
  • прогресс → трансформация (opacity, transform, scale, rotate и др.)
  • обновление происходит в реальном времени

Ключевое отличие от классических CSS-анимаций — отсутствие фиксированных таймингов. Движение становится функцией прокрутки, а не времени.

В экосистеме веб-анимаций Motion One предоставляет минималистичный API для построения таких эффектов без необходимости вручную работать с scrollTop, requestAnimationFrame и сложными вычислениями прогресса.


Базовая модель scroll-анимации

Любая scroll-анимация сводится к преобразованию диапазона:

scrollY: 0 → 1000
progress: 0 → 1
style: начальное → конечное состояние

Пример логики:

  • 0% прокрутки — элемент невидим
  • 50% — частично видим
  • 100% — полностью проявлен и трансформирован

Motion One абстрагирует эту модель через функцию scroll().


Функция scroll в Motion One

Основной инструмент для привязки анимации к прокрутке — scroll().

Она позволяет:

  • отслеживать прогресс прокрутки
  • применять трансформации
  • связывать анимацию с элементом или всей страницей

Базовый пример

import { scroll, animate } from "motion";

scroll(
  animate(".box", {
    opacity: [0, 1],
    transform: ["translateY(50px)", "translateY(0px)"]
  })
);

Здесь:

  • scroll() управляет прогрессом
  • animate() описывает изменение свойств
  • .box изменяется в зависимости от положения страницы

Привязка к конкретному элементу

Scroll-анимации могут быть связаны не только с окном браузера, но и с конкретным контейнером.

scroll(
  animate(".card", {
    scale: [0.8, 1],
    opacity: [0.2, 1]
  }),
  {
    target: document.querySelector(".container")
  }
);

В этом случае:

  • прокрутка отслеживается внутри .container
  • анимация зависит от скролла контейнера, а не всей страницы

Scroll-linked трансформации

Часто анимация строится вокруг изменения transform-значений:

  • translateX / translateY
  • scale
  • rotate
  • blur (через filter)

Пример эффекта появления карточек:

scroll(
  animate(".item", {
    opacity: [0, 1],
    transform: ["translateY(80px)", "translateY(0px)"]
  })
);

Такой подход позволяет создавать:

  • лендинги с динамическими блоками
  • параллакс-эффекты
  • постепенное появление контента

Управление диапазоном прокрутки

Важный аспект scroll-анимации — ограничение диапазона триггера.

В Motion One можно задавать точки начала и конца анимации.

scroll(
  animate(".hero", {
    opacity: [1, 0],
    scale: [1, 1.2]
  }),
  {
    offset: ["start start", "end start"]
  }
);

Интерпретация offset:

  • start start — начало элемента совпадает с началом viewport
  • end start — конец элемента достигает начала viewport

Таким образом формируется зона прогресса.


Прогрессивная анимация через timeline + scroll

Комбинация timeline и scroll позволяет строить сложные сцены.

import { scroll, timeline } from "motion";

scroll(
  timeline([
    [".title", { opacity: [0, 1], y: [40, 0] }],
    [".subtitle", { opacity: [0, 1], y: [40, 0] }, { at: "-0.3" }],
    [".button", { opacity: [0, 1], scale: [0.9, 1] }, { at: "-0.2" }]
  ])
);

Особенности:

  • элементы анимируются как единая сцена
  • scroll управляет прогрессом всей последовательности
  • timeline задаёт внутреннюю структуру

Scroll-driven параллакс

Параллакс — эффект разной скорости движения слоёв.

scroll(
  animate(".background", {
    transform: ["translateY(0px)", "translateY(-200px)"]
  })
);

scroll(
  animate(".foreground", {
    transform: ["translateY(0px)", "translateY(-50px)"]
  })
);

Результат:

  • фон движется быстрее
  • передний план медленнее
  • создаётся иллюзия глубины

Motion One позволяет синхронизировать такие эффекты без ручного вычисления скорости.


Сглаживание и контроль чувствительности

Scroll-анимации могут быть слишком «резкими», если не учитывать плавность изменения прогресса.

Встроенные механизмы позволяют:

  • сглаживать движение
  • управлять инерцией
  • регулировать отклик

Пример:

scroll(
  animate(".panel", {
    rotate: [0, 10]
  }),
  {
    offset: ["start end", "end start"]
  }
);

При этом движение не скачет, а интерполируется между состояниями.


Связка scroll + inView

Хотя scroll() управляет прогрессом, часто используется inView для первичной активации.

import { inView, animate } from "motion";

inView(".section", () => {
  animate(".section", {
    opacity: [0, 1],
    transform: ["translateY(60px)", "translateY(0px)"]
  });
});

Комбинация подходов:

  • inView — триггер появления
  • scroll — управление динамикой

Motion One поддерживает смешанные сценарии, где элемент сначала появляется, а затем продолжает реагировать на прокрутку.


Scroll как источник прогресса для нескольких элементов

Один scroll-поток может управлять множеством анимаций:

const animation = animate(".box", {
  opacity: [0, 1],
  scale: [0.8, 1]
});

scroll(animation);
scroll(animate(".text", {
  opacity: [0, 1],
  y: [30, 0]
}));

Так создаётся единый визуальный сценарий, где:

  • блоки появляются последовательно
  • движение синхронизировано
  • отсутствует необходимость в таймерах

Оптимизация scroll-анимаций

Scroll-анимации чувствительны к производительности. Основные принципы:

  • использовать transform вместо layout-свойств
  • избегать частых reflow
  • минимизировать количество активных анимаций
  • применять GPU-ускоряемые свойства

Motion One оптимизирован для работы через requestAnimationFrame, что снижает нагрузку на основной поток.


Типичные архитектуры scroll-анимаций

1. Лендинг с секциями

  • каждая секция — отдельный scroll-диапазон
  • внутри секции — локальные анимации

2. История/сторителлинг

  • scroll управляет последовательностью сцен
  • timeline синхронизирует элементы

3. Продуктовые демо

  • анимации интерфейса зависят от прокрутки
  • элементы UI «собираются» по мере скролла

Ошибки при проектировании scroll-анимаций

  • слишком длинные диапазоны без логики
  • отсутствие привязки к структуре контента
  • чрезмерное количество одновременно анимируемых элементов
  • попытка заменить весь интерфейс scroll-эффектами

В подходе Motion One важна умеренность: scroll должен усиливать интерфейс, а не подменять его поведение.