pipe для композиции функций

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


Основы pipe

Функция pipe принимает несколько функций в качестве аргументов и возвращает новую функцию, которая последовательно вызывает все переданные функции, передавая результат одной функции следующей. В GSAP это особенно полезно при работе с tween-ами, timeline и кастомными эффектами.

const pipe = (...fns) => (value) => fns.reduce((v, fn) => fn(v), value);
  • ...fns — массив функций.
  • value — исходное значение, передаваемое в первую функцию.
  • reduce последовательно применяет все функции к результату предыдущей.

Применение в GSAP

В GSAP pipe используется для построения сложных анимационных эффектов, где каждая функция модифицирует свойства объекта или создаёт новый tween. Пример цепочки для анимации DOM-элемента:

import { gsap } from "gsap";

const fadeIn = (element) => gsap.to(element, { opacity: 1, duration: 1 });
const moveRight = (element) => gsap.to(element, { x: 100, duration: 1 });
const scaleUp = (element) => gsap.to(element, { scale: 1.5, duration: 1 });

const animationPipeline = pipe(fadeIn, moveRight, scaleUp);

animationPipeline(document.querySelector(".box"));

Здесь:

  • fadeIn увеличивает прозрачность элемента.
  • moveRight смещает элемент по горизонтали.
  • scaleUp масштабирует элемент.
  • pipe гарантирует последовательное выполнение этих эффектов.

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

Использование pipe в сочетании с gsap.timeline позволяет строить динамические последовательности с точным контролем времени:

const tl = gsap.timeline({ defaults: { duration: 0.5 } });

const fadeIn = (element) => tl.to(element, { opacity: 1 });
const moveRight = (element) => tl.to(element, { x: 100 });
const scaleUp = (element) => tl.to(element, { scale: 1.5 });

const animationPipeline = pipe(fadeIn, moveRight, scaleUp);

animationPipeline(".box");
tl.play();
  • Все функции работают с одной таймлайной, что упрощает управление последовательностью.
  • Можно легко вставлять новые функции в pipeline без изменения основной структуры.

Передача параметров

Pipe не ограничен статическими значениями. Можно создавать функции, принимающие дополнительные аргументы, например длительность или задержку:

const fadeIn = (duration) => (element) => gsap.to(element, { opacity: 1, duration });
const moveRight = (distance) => (element) => gsap.to(element, { x: distance, duration: 1 });

const animationPipeline = pipe(fadeIn(1.5), moveRight(200));
animationPipeline(".box");
  • Использование каррирования позволяет настраивать анимацию без дублирования кода.
  • Позволяет строить гибкие и переиспользуемые эффекты для разных элементов.

Работа с массивами элементов

GSAP и pipe легко комбинируются при анимации коллекций DOM-элементов:

const elements = document.querySelectorAll(".box");

const fadeIn = (el) => gsap.to(el, { opacity: 1 });
const moveUp = (el) => gsap.to(el, { y: -50 });

elements.forEach(el => pipe(fadeIn, moveUp)(el));
  • Каждому элементу применяется та же последовательность анимаций.
  • Легко добавлять новые функции в pipeline, чтобы расширять эффекты.

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

GSAP позволяет создавать переиспользуемые эффекты через функцию registerEffect. Pipe помогает объединять эти эффекты в более сложные композиции:

gsap.registerEffect({
  name: "fadeMoveScale",
  effect: (targets, config) => pipe(
    el => gsap.to(el, { opacity: config.opacity }),
    el => gsap.to(el, { x: config.x }),
    el => gsap.to(el, { scale: config.scale })
  )(targets),
  defaults: { opacity: 1, x: 100, scale: 1.5 },
});

gsap.effects.fadeMoveScale(".box");
  • Позволяет строить модульные анимации, которые легко конфигурировать.
  • Pipeline упрощает объединение нескольких эффектов в единый, последовательный процесс.

Важные аспекты использования pipe с GSAP

  • Асинхронность анимаций: функции внутри pipe могут быть асинхронными, но pipe выполняет их последовательно, поэтому важно учитывать задержки и duration.
  • Модификация одной таймлайной: чтобы избежать конфликтов, функции лучше работать с одной timeline, либо использовать промисы для контроля окончания анимаций.
  • Расширяемость: новые функции легко добавлять в pipeline без изменения существующей структуры кода.
  • Чистота кода: pipe способствует созданию компактных и читаемых цепочек анимаций, что особенно важно для сложных проектов.

Pipe в GSAP превращает анимацию в настраиваемую, последовательную и легко расширяемую цепочку функций, позволяя строить сложные визуальные эффекты без дублирования кода и с полной управляемостью над таймингом.