Шейдеры и эффекты

ScrollMagic сам по себе не создаёт графические эффекты — он управляет состояниями и временем выполнения анимаций в зависимости от прокрутки. Визуальная составляющая реализуется через интеграцию с CSS, Canvas, WebGL или сторонними библиотеками, такими как GSAP.

Ключевая идея: позиция скролла → триггер → изменение свойств DOM или графического контекста.

Шейдеры и сложные эффекты чаще всего реализуются через:

  • WebGL (например, Three.js)
  • Canvas 2D
  • CSS-фильтры и трансформации
  • SVG-фильтры

ScrollMagic используется как механизм синхронизации.


Связка ScrollMagic и WebGL

При использовании WebGL (через Three.js) ScrollMagic управляет параметрами сцены: камерой, объектами, uniform-переменными шейдеров.

Пример структуры

const controller = new ScrollMagic.Controller();

const scene = new ScrollMagic.Scene({
    triggerElement: "#trigger",
    duration: 500
})
.on("progress", function (event) {
    const progress = event.progress;
    material.uniforms.uProgress.value = progress;
})
.addTo(controller);

Здесь значение progress (от 0 до 1) передаётся в шейдер как uniform.


Шейдеры: базовые принципы

Шейдер — это программа, выполняемая на GPU. В WebGL используются два типа:

  • Vertex Shader — отвечает за положение вершин
  • Fragment Shader — отвечает за цвет пикселей

Пример fragment shader

uniform float uProgress;

void main() {
    vec3 color = vec3(uProgress, 0.0, 1.0 - uProgress);
    gl_FragColor = vec4(color, 1.0);
}

ScrollMagic изменяет uProgress, создавая плавный переход цвета при прокрутке.


Управление uniform-переменными

Uniform-переменные — основной способ передачи данных в шейдер.

Связка с прокруткой

scene.on("progress", (e) => {
    shaderMaterial.uniforms.time.value = e.progress * 10.0;
});

Используемые параметры:

  • progress — нормализованное значение (0–1)
  • scrollPos — абсолютная позиция скролла
  • velocity — скорость прокрутки (рассчитывается вручную)

Эффекты искажения (Distortion)

Один из самых популярных эффектов — деформация изображения при прокрутке.

Пример fragment shader

uniform sampler2D uTexture;
uniform float uProgress;
varying vec2 vUv;

void main() {
    vec2 uv = vUv;
    uv.y += sin(uv.x * 10.0 + uProgress * 5.0) * 0.05;
    gl_FragColor = texture2D(uTexture, uv);
}

ScrollMagic изменяет uProgress, создавая анимацию волны.


Параллакс с использованием шейдеров

Классический параллакс можно значительно улучшить через шейдеры.

Подход:

  • Несколько текстур (слоёв)
  • Смещение каждого слоя с разной скоростью
vec2 uv = vUv;

vec4 layer1 = texture2D(tex1, uv + uProgress * 0.1);
vec4 layer2 = texture2D(tex2, uv + uProgress * 0.2);

gl_FragColor = mix(layer1, layer2, 0.5);

ScrollMagic управляет uProgress, создавая глубину.


Переходы между изображениями

ScrollMagic идеально подходит для контроля переходов (image transitions).

Пример эффекта dissolve

uniform sampler2D from;
uniform sampler2D to;
uniform float progress;

void main() {
    vec4 color1 = texture2D(from, vUv);
    vec4 color2 = texture2D(to, vUv);
    gl_FragColor = mix(color1, color2, progress);
}

Управление через ScrollMagic

scene.on("progress", (e) => {
    material.uniforms.progress.value = e.progress;
});

Эффекты с использованием шума (Noise)

Шум используется для создания органичных переходов и искажений.

Пример с Perlin Noise

float noise = sin(vUv.x * 10.0 + uProgress * 10.0);
vec2 uv = vUv + noise * 0.02;

Эффекты:

  • “растворение”
  • “глитч”
  • “жидкость”

Глитч-эффект

Популярный визуальный эффект — цифровое искажение.

float glitch = step(0.9, sin(uProgress * 50.0));
vec2 uv = vUv;

uv.x += glitch * 0.05;

gl_FragColor = texture2D(uTexture, uv);

ScrollMagic задаёт момент появления “сбоев”.


Эффекты с Canvas 2D

Если WebGL избыточен, можно использовать Canvas.

Пример

scene.on("progress", (e) => {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    const offset = e.progress * 100;

    ctx.drawImage(image, offset, 0);
});

Возможности:

  • размытие
  • масштабирование
  • смещение
  • альфа-композиция

CSS-фильтры и ScrollMagic

Простейшие эффекты достигаются без WebGL.

Пример

scene.on("progress", (e) => {
    const blur = e.progress * 10;
    element.style.filter = `blur(${blur}px)`;
});

Другие фильтры:

  • brightness
  • contrast
  • grayscale
  • hue-rotate

SVG-фильтры

SVG позволяет создавать сложные эффекты без WebGL.

Пример blur + displacement

<filter id="distort">
  <feTurbulence baseFrequency="0.01" numOctaves="2" result="turb"/>
  <feDisplacementMap in="SourceGraphic" in2="turb" scale="20"/>
</filter>

ScrollMagic меняет параметр scale:

scene.on("progress", (e) => {
    displacement.setAttribute("scale", e.progress * 50);
});

Связка с GSAP для сложных эффектов

ScrollMagic часто используется с GSAP Timeline.

const tween = gsap.to(obj, {
    value: 1,
    onUpdate: () => {
        material.uniforms.progress.value = obj.value;
    }
});

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

Преимущества:

  • сглаживание
  • easing-функции
  • сложные последовательности

Оптимизация производительности

Работа с шейдерами и ScrollMagic требует внимания к производительности.

Основные правила:

Минимизация обновлений

  • не обновлять uniform без необходимости
  • использовать throttling

GPU-нагрузка

  • избегать сложных циклов в шейдерах
  • уменьшать разрешение текстур

ScrollMagic

  • уменьшать количество сцен
  • объединять эффекты

Синхронизация нескольких эффектов

Несколько шейдеров могут быть синхронизированы одной сценой.

scene.on("progress", (e) => {
    shader1.uniforms.uProgress.value = e.progress;
    shader2.uniforms.uProgress.value = e.progress;
});

Позволяет создавать:

  • комплексные переходы
  • мультислойные анимации
  • кинематографические сцены

Продвинутые техники

Использование velocity скролла

let lastScroll = 0;

scene.on("update", (e) => {
    const velocity = e.scrollPos - lastScroll;
    lastScroll = e.scrollPos;

    material.uniforms.velocity.value = velocity;
});

Применение:

  • инерция
  • динамическое размытие
  • реактивные эффекты

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

  • distortion + blur
  • noise + dissolve
  • parallax + color shift

ScrollMagic управляет всеми параметрами одновременно, создавая сложные визуальные сцены.


Эффекты на основе времени и скролла

Комбинация времени и прокрутки:

scene.on("progress", (e) => {
    material.uniforms.time.value = performance.now() * 0.001;
    material.uniforms.scroll.value = e.progress;
});

Даёт:

  • живые анимации
  • независимость от FPS скролла

Архитектура проекта с эффектами

Типичная структура:

/js
  scroll.js
  shaders.js
  scene.js
/shaders
  vertex.glsl
  fragment.glsl

Рекомендации:

  • отделять логику ScrollMagic
  • хранить шейдеры отдельно
  • использовать единый контроллер состояний

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

Рывки анимации

  • отсутствие easing
  • слишком резкие изменения uniform

Падение FPS

  • сложные шейдеры
  • высокое разрешение canvas

Несинхронность

  • несколько контроллеров ScrollMagic
  • неправильные duration

Практическое применение

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