Web Animations API

Atomico — это современная библиотека для создания веб-компонентов на JavaScript, которая гармонично интегрируется с нативными API браузера, включая Web Animations API (WAAPI). Использование WAAPI позволяет создавать высокопроизводительные анимации без сторонних библиотек и управлять ими с помощью JavaScript.


Импорт необходимых функций

Для работы с Atomico необходимо импортировать функции создания компонента и управления его состоянием:

import { c, useRef, useEffect } from "atomico";

useRef используется для получения ссылки на DOM-элемент, на котором будет применяться анимация, а useEffect позволяет инициализировать анимацию при монтировании компонента.


Создание анимации через WAAPI

Web Animations API предоставляет метод animate() на DOM-элементе, который принимает два аргумента:

  1. Ключевые кадры (Keyframes) — массив объектов с CSS-свойствами, которые будут изменяться.
  2. Опции анимации (Timing Options) — объект с параметрами продолжительности, повторения, задержки и направления.

Пример создания базовой анимации в Atomico:

function AnimatedBox() {
    const boxRef = useRef();

    useEffect(() => {
        const animation = boxRef.current.animate(
            [
                { transform: "translateX(0px)", opacity: 0 },
                { transform: "translateX(100px)", opacity: 1 }
            ],
            {
                duration: 1000,
                iterations: Infinity,
                direction: "alternate",
                easing: "ease-in-out"
            }
        );

        return () => animation.cancel();
    }, []);

    return <div ref={boxRef} style={{ width: "100px", height: "100px", background: "tomato" }}></div>;
}

export default c(AnimatedBox);

Ключевые моменты:

  • ref.current.animate() создает анимацию на конкретном элементе.
  • iterations: Infinity делает анимацию бесконечной.
  • direction: "alternate" позволяет чередовать направление анимации.
  • Возврат функции animation.cancel() внутри useEffect гарантирует корректное удаление анимации при размонтировании компонента.

Управление анимацией

WAAPI позволяет управлять анимацией динамически:

  • animation.play() — запускает анимацию.
  • animation.pause() — останавливает анимацию.
  • animation.reverse() — меняет направление.
  • animation.currentTime — текущий прогресс анимации в миллисекундах.
  • animation.playbackRate — скорость воспроизведения.

Пример динамического управления через Atomico:

import { useState } from "atomico";

function ControlledBox() {
    const boxRef = useRef();
    const [animation, setAnimation] = useState(null);

    useEffect(() => {
        const anim = boxRef.current.animate(
            [{ transform: "scale(1)" }, { transform: "scale(1.5)" }],
            { duration: 500, fill: "forwards" }
        );
        setAnimation(anim);
    }, []);

    return (
        <div>
            <div ref={boxRef} style={{ width: "100px", height: "100px", background: "skyblue" }}></div>
            <button onCl ick={() => animation?.play()}>Play</button>
            <button onCl ick={() => animation?.pause()}>Pause</button>
            <button onCl ick={() => animation?.reverse()}>Reverse</button>
        </div>
    );
}

export default c(ControlledBox);

Особенности управления:

  • Состояние animation хранит объект анимации WAAPI для дальнейшего взаимодействия.
  • Кнопки напрямую вызывают методы управления анимацией.

Связь с реактивностью Atomico

WAAPI в Atomico отлично сочетается с реактивными состояниями. Изменение состояния может влиять на параметры анимации без перерисовки всего компонента:

function ReactiveBox() {
    const boxRef = useRef();
    const [scale, setScale] = useState(1);

    useEffect(() => {
        const anim = boxRef.current.animate(
            [{ transform: `scale(${scale})` }],
            { duration: 300, fill: "forwards" }
        );
        return () => anim.cancel();
    }, [scale]);

    return (
        <div>
            <div ref={boxRef} style={{ width: "100px", height: "100px", background: "limegreen" }}></div>
            <button onCl ick={() => setScale(scale + 0.1)}>Increase Scale</button>
        </div>
    );
}

export default c(ReactiveBox);

Важные моменты:

  • WAAPI реагирует на изменение состояния через useEffect.
  • fill: "forwards" позволяет сохранять конечное состояние анимации после её завершения.
  • Использование реактивного состояния обеспечивает плавное управление анимацией при изменении данных.

Интеграция нескольких анимаций

Web Animations API поддерживает создание нескольких анимаций на одном элементе. Каждая анимация независима, что позволяет комбинировать эффекты:

useEffect(() => {
    const move = boxRef.current.animate(
        [{ transform: "translateX(0)" }, { transform: "translateX(200px)" }],
        { duration: 1000, fill: "forwards" }
    );

    const fade = boxRef.current.animate(
        [{ opacity: 1 }, { opacity: 0 }],
        { duration: 1000, fill: "forwards" }
    );

    return () => {
        move.cancel();
        fade.cancel();
    };
}, []);

Применение нескольких анимаций:

  • Позволяет создавать сложные последовательности движений.
  • WAAPI автоматически синхронизирует анимации по времени.
  • Можно комбинировать свойства transform, opacity, color и другие CSS-свойства.

Взаимодействие с событиями анимации

WAAPI поддерживает события жизненного цикла анимации: onfinish, oncancel, которые позволяют выполнять действия после завершения или отмены анимации:

useEffect(() => {
    const anim = boxRef.current.animate(
        [{ transform: "rotate(0deg)" }, { transform: "rotate(360deg)" }],
        { duration: 2000 }
    );

    anim.onfin ish = () => console.log("Анимация завершена");

    return () => anim.cancel();
}, []);

Особенности событий:

  • onfinish вызывается после окончания всех итераций.
  • oncancel срабатывает при вызове animation.cancel().
  • Можно динамически менять обработчики событий в зависимости от состояния компонента.

Web Animations API в сочетании с Atomico обеспечивает высокую производительность и гибкость анимаций. Использование ref, useEffect и реактивных состояний позволяет создавать сложные визуальные эффекты, управлять ими динамически и интегрировать с другими функциональными компонентами без лишней нагрузки на DOM.