Физические симуляции

Физические симуляции позволяют придать анимациям ощущение реалистичности: инерцию, сопротивление, ускорение, замедление. В контексте ScrollMagic такие эффекты реализуются через синхронизацию прокрутки страницы с динамическими значениями, имитирующими физические процессы.

ScrollMagic сам по себе не является физическим движком. Он управляет сценами (Scene) и контроллером (Controller), а физика добавляется за счёт интеграции с анимационными библиотеками, такими как GSAP, или через собственные вычисления.

Инерция и сглаживание прокрутки

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

Пример реализации с использованием requestAnimationFrame:

let current = 0;
let target = 0;
const ease = 0.1;

window.addEventListener("scroll", () => {
  target = window.scrollY;
});

function update() {
  current += (target - current) * ease;

  // здесь можно управлять анимацией
  document.querySelector(".box").style.transform =
    `translateY(${current}px)`;

  requestAnimationFrame(update);
}

update();

Интеграция со ScrollMagic:

const controller = new ScrollMagic.Controller();

const scene = new ScrollMagic.Scene({
  triggerElement: ".trigger",
  duration: 500
})
.addTo(controller)
.on("progress", (event) => {
  target = event.progress * 500;
});

В этом случае ScrollMagic задаёт целевое значение, а сглаживание создаёт физическую плавность.

Ускорение и замедление

Физические симуляции часто включают переменное ускорение. В ScrollMagic это достигается через нелинейные функции интерполяции.

Пример с использованием GSAP:

const tween = gsap.to(".box", {
  y: 500,
  ease: "power3.out"
});

new ScrollMagic.Scene({
  triggerElement: ".trigger",
  duration: 500
})
.setTween(tween)
.addTo(controller);

Типы easing-функций:

  • linear — равномерное движение
  • power — ускорение/замедление
  • elastic — эффект пружины
  • bounce — отскок

Эти функции имитируют физические свойства: массу, упругость, сопротивление.

Эффект пружины

Пружинная динамика — один из наиболее выразительных физических эффектов. Она создаёт ощущение живого взаимодействия.

Пример через пользовательскую функцию:

function spring(progress) {
  return 1 - Math.cos(progress * Math.PI * 2) * Math.exp(-progress * 5);
}

new ScrollMagic.Scene({
  triggerElement: ".trigger",
  duration: 500
})
.on("progress", (event) => {
  const value = spring(event.progress);
  document.querySelector(".box").style.transform =
    `translateY(${value * 500}px)`;
})
.addTo(controller);

Характеристики пружины:

  • амплитуда (высота колебаний)
  • затухание (скорость остановки)
  • частота (количество колебаний)

Параллакс с физическим поведением

Параллакс-эффекты часто выглядят искусственно из-за линейного движения. Добавление физики делает их более естественными.

new ScrollMagic.Scene({
  triggerElement: ".section",
  duration: 1000
})
.on("progress", (event) => {
  const speed = 0.5;
  const offset = Math.pow(event.progress, 2) * 300;

  document.querySelector(".bg").style.transform =
    `translateY(${offset * speed}px)`;
})
.addTo(controller);

Использование квадратичной зависимости создаёт эффект ускорения, как при падении объекта.

Симуляция сопротивления (drag)

Сопротивление воздуха или трение можно имитировать через постепенное уменьшение скорости изменения значения.

let velocity = 0;

new ScrollMagic.Scene({
  triggerElement: ".trigger",
  duration: 500
})
.on("progress", (event) => {
  velocity += (event.progress - velocity) * 0.05;

  document.querySelector(".box").style.transform =
    `translateY(${velocity * 500}px)`;
})
.addTo(controller);

Чем меньше коэффициент, тем сильнее “сопротивление”.

Масса и инерция объектов

Можно моделировать различную “массу” элементов, изменяя коэффициенты сглаживания.

function createPhysicsObject(selector, mass) {
  let current = 0;

  return (target) => {
    current += (target - current) / mass;

    document.querySelector(selector).style.transform =
      `translateY(${current}px)`;
  };
}

const heavy = createPhysicsObject(".heavy", 20);
const light = createPhysicsObject(".light", 5);

new ScrollMagic.Scene({
  triggerElement: ".trigger",
  duration: 500
})
.on("progress", (event) => {
  const target = event.progress * 500;

  heavy(target);
  light(target);
})
.addTo(controller);

Эффект:

  • лёгкие элементы реагируют быстро
  • тяжёлые — медленно и плавно

Комбинирование эффектов

Физические симуляции становятся выразительными при сочетании нескольких факторов:

  • инерция + пружина
  • параллакс + сопротивление
  • масса + ускорение

Пример:

let current = 0;
let velocity = 0;

new ScrollMagic.Scene({
  triggerElement: ".trigger",
  duration: 600
})
.on("progress", (event) => {
  const target = event.progress * 600;

  velocity += (target - current) * 0.1;
  velocity *= 0.8; // трение
  current += velocity;

  document.querySelector(".box").style.transform =
    `translateY(${current}px)`;
})
.addTo(controller);

Такой подход даёт поведение, близкое к реальной механике.

Производительность

Физические вычисления выполняются часто (при каждом кадре), поэтому важно:

  • избегать лишних DOM-операций
  • использовать transform вместо top/left
  • кешировать селекторы
  • применять requestAnimationFrame

ScrollMagic не ограничивает частоту обновлений, поэтому ответственность за оптимизацию лежит на разработчике.

Архитектура физического слоя

Для крупных проектов удобно выделять физику в отдельный модуль:

class PhysicsValue {
  constructor(mass = 10, friction = 0.8) {
    this.value = 0;
    this.velocity = 0;
    this.mass = mass;
    this.friction = friction;
  }

  update(target) {
    this.velocity += (target - this.value) / this.mass;
    this.velocity *= this.friction;
    this.value += this.velocity;

    return this.value;
  }
}

Использование:

const physics = new PhysicsValue(15, 0.85);

new ScrollMagic.Scene({
  triggerElement: ".trigger",
  duration: 500
})
.on("progress", (event) => {
  const y = physics.update(event.progress * 500);

  document.querySelector(".box").style.transform =
    `translateY(${y}px)`;
})
.addTo(controller);

Такой подход делает код масштабируемым и управляемым.

Интеграция с GSAP Physics Plugins

Для более сложных симуляций используются плагины GSAP:

  • Physics2DPlugin
  • InertiaPlugin

Пример:

gsap.to(".box", {
  physics2D: {
    velocity: 200,
    angle: 90,
    gravity: 500
  }
});

В связке со ScrollMagic:

new ScrollMagic.Scene({
  triggerElement: ".trigger",
  duration: 300
})
.setTween(".box", {
  y: 400,
  ease: "bounce.out"
})
.addTo(controller);

Это позволяет комбинировать скролл и физические эффекты без ручных расчётов.

Типичные ошибки

Резкие скачки значений Причина: отсутствие сглаживания

Дёрганая анимация Причина: обновление через scroll вместо requestAnimationFrame

Нереалистичное движение Причина: линейная интерполяция без easing

Проблемы с производительностью Причина: частые изменения layout (top/left вместо transform)

Практические сценарии

  • “липкие” элементы с инерцией
  • карточки с эффектом массы
  • прокрутка с “живым” параллаксом
  • интерфейсы с ощущением физического взаимодействия

Физические симуляции в ScrollMagic позволяют выйти за рамки стандартных анимаций и создавать интерфейсы с глубиной и динамикой, приближённой к реальному миру.