Очередь анимаций в Velocity.js строится вокруг механизма, который определяет порядок исполнения эффектов для каждого отдельного элемента. По умолчанию все анимации, запущенные на одном DOM-элементе, складываются в последовательную очередь и выполняются одна за другой. Это поведение наследует подход, знакомый по jQuery, но в Velocity.js он расширен возможностью управления параллельным исполнением, независимыми очередями и тонкой настройкой конкурирующих анимационных потоков.
Каждый вызов анимации в Velocity.js может быть частью очереди или выполняться вне её. Очередь привязана к конкретному элементу, а не к глобальному контексту. Это означает, что разные элементы могут одновременно выполнять свои собственные последовательности без взаимного блокирования, даже если внутри каждого элемента сохраняется строгий порядок.
При стандартном запуске анимации:
Velocity(element, { opacity: 1 }, { duration: 300 });
Velocity(element, { translateX: 200 }, { duration: 300 });
второй вызов начнёт выполняться только после завершения первого. Такое поведение формирует линейную очередь. Внутри Velocity.js это реализуется через внутренний стек задач, где каждый новый эффект добавляется в конец очереди.
Ключевой аспект этой модели — последовательность гарантируется только при совпадении очереди. Если анимации принадлежат одной очереди, они никогда не пересекаются по времени выполнения.
Velocity.js поддерживает несколько независимых очередей на одном элементе. Это позволяет разделять анимационные потоки по логическим каналам.
Velocity(element, { opacity: 0.5 }, { queue: "fx" });
Velocity(element, { translateX: 200 }, { queue: "transform" });
В этом случае обе анимации стартуют независимо, поскольку принадлежат разным очередям. Каждая очередь ведёт собственную последовательность команд, не блокируя другую.
Такая модель позволяет организовать параллельные изменения разных CSS-аспектов:
fx может отвечать за прозрачность и масштабtransform может отвечать за перемещенияrotation может управлять вращениемОчереди становятся изолированными каналами управления состоянием элемента.
Самый прямой способ параллелизма — отключение очереди:
Velocity(element, { opacity: 0.2 }, { queue: false });
Velocity(element, { translateX: 300 }, { queue: false });
Обе анимации запускаются одновременно и не помещаются в очередь вообще. Внутренне Velocity.js обходит систему очередей и инициирует отдельные таймеры для каждого эффекта.
Такой подход полезен, когда требуется одновременное изменение свойств, не зависящих друг от друга. Однако он исключает контроль порядка выполнения и усложняет синхронизацию завершения.
При передаче коллекции элементов Velocity.js применяет одинаковую анимацию ко всем узлам. При этом каждый элемент сохраняет собственную очередь:
Velocity([el1, el2, el3], { opacity: 0 }, { duration: 400 });
Если затем добавить следующую анимацию:
Velocity([el1, el2, el3], { translateY: 100 }, { duration: 400 });
каждый элемент будет выполнять свою последовательность независимо. Однако внутри каждого элемента порядок сохранится. Это создаёт эффект синхронной групповой анимации с внутренней очередностью.
При использовании нескольких очередей возможна ситуация, когда разные анимации затрагивают одни и те же CSS-свойства. Velocity.js не блокирует такие конфликты автоматически, а применяет последнее значение, вычисленное в текущем кадре анимации.
Если одновременно выполняются:
Velocity(element, { left: "100px" }, { queue: "a" });
Velocity(element, { left: "200px" }, { queue: "b" });
результат зависит от тайминга кадров. Последняя применённая интерполяция перезаписывает значение свойства. Это важно учитывать при проектировании параллельных очередей, особенно для позиционных свойств.
Комбинация очередей и параллельного запуска позволяет строить сложные сценарии анимации:
Velocity(element, { opacity: 1 }, { queue: "fx" });
Velocity(element, { translateX: 100 }, { queue: "transform" });
Velocity(element, { rotateZ: 45 }, { queue: "transform" });
Velocity(element, { scale: 1.2 }, { queue: "fx" });
Здесь формируются две независимые линии:
fx — управляет визуальной выразительностьюtransform — управляет геометриейВнутри каждой очереди сохраняется строгая последовательность, но между ними присутствует параллелизм. Это позволяет синхронизировать сложные эффекты без ручного управления таймингами.
Velocity.js предоставляет средства управления очередями, включая остановку и очистку. При необходимости можно прервать выполнение текущей очереди:
Velocity(element, "stop", "transform");
или остановить все очереди сразу:
Velocity(element, "stop", true);
Остановка очереди влияет только на соответствующий поток. Другие очереди продолжают работу, если они не затронуты командой остановки. Это критически важно для систем с параллельными анимациями, где разные визуальные слои должны управляться независимо.
При использовании параллельных очередей возникает задача координации завершения. Velocity.js предоставляет Promise-подобное завершение каждой анимации:
Velocity(element, { opacity: 0 }).then(() => {
// выполнение после завершения конкретной анимации
});
Однако при параллельных очередях каждая ветка завершится независимо. Для синхронизации требуется логическая агрегация завершений всех потоков.
Внутри Velocity.js каждая очередь представляет собой структуру задач, связанных с конкретным DOM-элементом. При добавлении анимации происходит:
requestAnimationFrameПри использовании queue: false этап регистрации в
очереди пропускается, и анимация становится автономной единицей
исполнения.
Параллельность достигается не через многопоточность, а через независимые циклы интерполяции, которые синхронизируются с кадровым обновлением браузера.
Модель параллельных очередей позволяет разделять ответственность между визуальными слоями интерфейса. Геометрические трансформации, прозрачность, цветовые эффекты и декоративные изменения могут выполняться независимо, снижая сложность управления анимациями.
Такой подход уменьшает необходимость в ручной синхронизации таймингов и делает поведение интерфейса более предсказуемым при увеличении количества одновременно активных эффектов.