Begin и complete коллбэки

В системе анимаций Velocity.js управление жизненным циклом эффекта строится вокруг набора коллбэков, которые позволяют встраивать пользовательскую логику в ключевые моменты выполнения анимации. Среди них особое значение имеют функции begin и complete, отвечающие за начало и завершение анимационного цикла.


Момент инициации анимации: begin

Коллбэк begin вызывается строго один раз для каждого элемента в момент старта анимации, до того как начнут изменяться CSS-свойства. Это делает его удобным инструментом для подготовки интерфейса к изменению состояния.

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

  • вызывается до первого кадра анимации
  • срабатывает для каждого элемента отдельно при множественном выборе
  • не повторяется при повторном запуске, если не создаётся новый tween
  • получает доступ к DOM-элементу через this

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

Velocity(element, { opacity: 0 }, {
    duration: 1000,
    begin: function(elements) {
        // логика перед стартом анимации
    }
});

Контекст this внутри begin указывает на текущий DOM-элемент, что позволяет выполнять локальные операции без дополнительного поиска в DOM.


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

Коллбэк используется в сценариях, где требуется синхронизировать состояние интерфейса до старта визуального перехода:

  • добавление классов состояния
  • блокировка пользовательского ввода
  • подготовка стартовых значений
  • логирование начала анимации
  • запуск вспомогательных эффектов (например, затемнение фона)

Пример управления состоянием:

Velocity(element, {
    width: "300px"
}, {
    duration: 600,
    begin: function() {
        this.classList.add("animating");
    }
});

При работе с группой элементов begin вызывается для каждого элемента, поэтому состояние может быть установлено индивидуально.


Завершение анимации: complete

Коллбэк complete срабатывает после полного завершения анимации, включая все промежуточные кадры и завершение очереди анимаций для конкретного элемента. Он является финальной точкой жизненного цикла tween-а.

Ключевые характеристики:

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

Сигнатура:

Velocity(element, { opacity: 1 }, {
    duration: 1000,
    complete: function(elements) {
        // финальная логика
    }
});

Использование complete для синхронизации логики

Коллбэк завершения часто применяется для построения последовательностей и управления состояниями интерфейса после анимации.

Распространённые сценарии:

  • удаление временных классов
  • активация следующего шага интерфейса
  • разблокировка взаимодействия
  • запуск последующих анимаций вручную
  • очистка временных стилей или данных

Пример:

Velocity(element, {
    translateX: "200px"
}, {
    duration: 800,
    complete: function() {
        this.classList.remove("animating");
        this.classList.add("done");
    }
});

Различие поведения begin и complete в очередях

Velocity.js использует систему очередей (queue), и поведение коллбэков зависит от их положения в цепочке анимаций.

  • begin срабатывает до старта конкретного шага очереди
  • complete вызывается после завершения шага, включая ожидание очереди
  • при последовательных вызовах Velocity каждый блок анимации имеет собственный цикл begin/complete

Пример цепочки:

Velocity(element, { opacity: 0 }, {
    duration: 500,
    begin: function() {
        this.dataset.state = "fade-out";
    },
    complete: function() {
        this.dataset.state = "faded";
    }
}).velocity({ opacity: 1 }, {
    duration: 500,
    begin: function() {
        this.dataset.state = "fade-in";
    },
    complete: function() {
        this.dataset.state = "visible";
    }
});

Множественные элементы и особенности вызова

При работе с коллекцией DOM-элементов Velocity вызывает begin и complete для каждого элемента отдельно. Это важно учитывать при управлении глобальными состояниями.

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

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

Для синхронизации используют внешние счётчики:

let counter = 0;

Velocity(items, {
    opacity: 1
}, {
    duration: 700,
    begin: function() {
        counter++;
    },
    complete: function() {
        counter--;
        if (counter === 0) {
            console.log("Все анимации завершены");
        }
    }
});

Контекст выполнения и управление состоянием

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

Корректный вариант:

Velocity(element, {
    scale: 1.2
}, {
    begin: function() {
        this.style.willChange = "transform";
    },
    complete: function() {
        this.style.willChange = "auto";
    }
});

Некорректный вариант:

begin: () => {
    this.classList.add("active"); // контекст потерян
}

Синхронизация цепочек анимаций через complete

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

Velocity(box, { height: "200px" }, {
    duration: 400,
    complete: function() {
        Velocity(this, { width: "200px" }, {
            duration: 400
        });
    }
});

Такой подход позволяет строить сложные сценарии интерфейсных переходов, где каждый этап зависит от завершения предыдущего.


Поведение при прерывании анимации

Если анимация прерывается вызовом нового Velocity на тот же элемент, поведение коллбэков меняется:

  • begin нового tween-а будет вызван немедленно
  • complete предыдущего может не выполниться, если анимация была остановлена без завершения
  • при использовании queue: false логика становится параллельной, что влияет на порядок вызовов

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


Комбинирование begin и complete в одной логике

На практике оба коллбэка часто используются совместно для полного контроля жизненного цикла анимации:

Velocity(panel, {
    opacity: 0
}, {
    duration: 500,
    begin: function() {
        this.classList.add("transitioning");
    },
    complete: function() {
        this.classList.remove("transitioning");
        this.classList.add("hidden");
    }
});

Такая структура обеспечивает чёткое разделение:

  • begin отвечает за подготовку
  • complete отвечает за фиксацию итогового состояния