Particle-система — это совокупность множества мелких визуальных объектов (частиц), которые управляются единым механизмом анимации. В контексте ScrollMagic частицы не просто анимируются во времени, а привязываются к положению прокрутки страницы. Это позволяет создавать динамические сцены, реагирующие на действия пользователя.
Основные компоненты:
Наиболее подходящий вариант для большого количества частиц (сотни и тысячи).
Преимущества:
Недостатки:
Подходит для небольшого количества частиц.
Преимущества:
Недостатки:
Используются редко, только для простых эффектов.
class Particle {
constructor(x, y, size, speed) {
this.x = x;
this.y = y;
this.size = size;
this.speed = speed;
}
update(progress) {
this.y += this.speed * progress;
}
draw(ctx) {
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
}
}
Создание системы:
const particles = [];
for (let i = 0; i < 200; i++) {
particles.push(
new Particle(
Math.random() * canvas.width,
Math.random() * canvas.height,
Math.random() * 3,
Math.random() * 2
)
);
}
Создание контроллера и сцены:
const controller = new ScrollMagic.Controller();
const scene = new ScrollMagic.Scene({
triggerElement: "#trigger",
duration: 1000
})
.addTo(controller);
Привязка обновления частиц к прогрессу сцены:
scene.on("progress", (event) => {
const progress = event.progress;
updateParticles(progress);
renderParticles();
});
Функция обновления должна учитывать прогресс прокрутки:
function updateParticles(progress) {
particles.forEach(particle => {
particle.update(progress);
});
}
Рендеринг:
function renderParticles() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
particles.forEach(particle => {
particle.draw(ctx);
});
}
ScrollMagic предоставляет значение progress от 0 до 1.
Это ключевой параметр для управления поведением частиц.
Примеры:
ctx.globalAlpha = progress;
particle.y += particle.speed * (1 + progress * 5);
particle.size = baseSize * (1 + progress);
Разные частицы движутся с разной скоростью:
particle.y += particle.speed * (progress * particle.depth);
Где depth — коэффициент “глубины”.
particle.x += Math.cos(particle.angle) * progress * 100;
particle.y += Math.sin(particle.angle) * progress * 100;
const dx = targetX - particle.x;
const dy = targetY - particle.y;
particle.x += dx * 0.05 * progress;
particle.y += dy * 0.05 * progress;
Оптимальное количество:
Хотя ScrollMagic управляет прогрессом, отрисовку лучше синхронизировать:
function animate() {
renderParticles();
requestAnimationFrame(animate);
}
animate();
Создание и удаление частиц — дорогостоящая операция.
Решение:
const pool = [];
function getParticle() {
return pool.length ? pool.pop() : new Particle(0, 0, 0, 0);
}
function releaseParticle(p) {
pool.push(p);
}
ScrollMagic часто используется вместе с GSAP для сложных анимаций.
Пример:
const tween = gsap.to(particles, {
duration: 1,
y: "+=200",
stagger: 0.01
});
new ScrollMagic.Scene({
triggerElement: "#trigger",
duration: 500
})
.setTween(tween)
.addTo(controller);
scene.on("update", (event) => {
const direction = event.scrollDirection;
particles.forEach(p => {
p.speed = direction === "REVERSE" ? -Math.abs(p.speed) : Math.abs(p.speed);
});
});
Для очень сложных систем применяются:
ScrollMagic управляет только прогрессом:
scene.on("progress", (event) => {
shader.uniforms.uProgress.value = event.progress;
});
Добавление “времени жизни”:
class Particle {
constructor() {
this.life = 1;
}
update(progress) {
this.life -= 0.01 * progress;
}
isAlive() {
return this.life > 0;
}
}
Очистка:
particles = particles.filter(p => p.isAlive());
Можно создавать разные particle-эффекты для разных секций:
new ScrollMagic.Scene({
triggerElement: "#section1",
duration: 500
})
.on("progress", updateParticlesLayer1);
new ScrollMagic.Scene({
triggerElement: "#section2",
duration: 800
})
.on("progress", updateParticlesLayer2);
Сложные сцены строятся через слои:
Каждый слой имеет свой коэффициент:
particle.speed *= layerMultiplier;
scene.addIndicators();
Позволяет визуально видеть:
Particle-система должна быть модульной:
Пример менеджера:
class ParticleSystem {
constructor() {
this.particles = [];
}
update(progress) {
this.particles.forEach(p => p.update(progress));
}
render(ctx) {
this.particles.forEach(p => p.draw(ctx));
}
}
particle.y += particle.speed * (0.5 + progress * 2);
Дополнительно:
particle.size = baseSize * (1 + progress * 3);
particle.y += particle.speed * progress * 10;
const isMobile = window.innerWidth < 768;
const particleCount = isMobile ? 100 : 500;
Рекомендуется выносить настройки:
const config = {
count: 300,
speed: 2,
size: 3,
color: "#ffffff"
};
Это упрощает адаптацию и повторное использование системы.
Particle-системы часто комбинируются с:
ScrollMagic позволяет синхронизировать всё через один
progress.
Для крупного проекта:
Это позволяет: