Физические симуляции позволяют придать анимациям ощущение реалистичности: инерцию, сопротивление, ускорение, замедление. В контексте 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-функций:
Эти функции имитируют физические свойства: массу, упругость, сопротивление.
Пружинная динамика — один из наиболее выразительных физических эффектов. Она создаёт ощущение живого взаимодействия.
Пример через пользовательскую функцию:
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);
Использование квадратичной зависимости создаёт эффект ускорения, как при падении объекта.
Сопротивление воздуха или трение можно имитировать через постепенное уменьшение скорости изменения значения.
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);
Такой подход даёт поведение, близкое к реальной механике.
Физические вычисления выполняются часто (при каждом кадре), поэтому важно:
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:
Пример:
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 позволяют выйти за рамки стандартных анимаций и создавать интерфейсы с глубиной и динамикой, приближённой к реальному миру.