Библиотека mo.js построена вокруг модульного подхода, где каждая сущность анимации представлена отдельным, изолированным компонентом. Такой подход позволяет создавать сложные анимации, комбинируя простые элементы без жёсткой связности между ними.
Модули в mo.js — это не просто файлы или классы, а логические единицы, каждая из которых отвечает за конкретный аспект анимации: геометрию, временные параметры, эффекты или взаимодействие.
1. Изоляция ответственности Каждый модуль выполняет строго определённую задачу:
Это снижает сложность и упрощает отладку.
2. Переиспользуемость Один и тот же модуль может использоваться в разных анимациях без изменений.
3. Композиция вместо наследования mo.js активно использует композицию: сложные анимации создаются путём объединения модулей, а не расширения классов.
4. Декларативный стиль Анимации описываются через параметры, а не через последовательность императивных действий.
Отвечают за создание и отображение визуальных объектов.
Пример:
const circle = new mojs.Shape({
shape: 'circle',
radius: 50,
fill: 'red'
});
Ключевые свойства:
shape — тип фигурыradius, width, height —
размерыfill, stroke — стилиКаждый Shape — независимый модуль, который можно анимировать отдельно.
Управляют временной интерполяцией значений.
const tween = new mojs.Tween({
duration: 1000,
onUpdate: (progress) => {
console.log(progress);
}
});
Особенности:
Создают сложные анимации частиц.
const burst = new mojs.Burst({
count: 10,
radius: { 0: 100 }
});
Комбинируют в себе:
Организуют последовательность и синхронизацию анимаций.
const timeline = new mojs.Timeline();
timeline.add(circle, burst);
timeline.play();
Функции:
Определяют характер изменения значений во времени.
mojs.easing.ease.out
Модульный подход позволяет:
Отвечают за интерполяцию значений между начальным и конечным состоянием.
Пример:
radius: { 0: 100 }
Здесь создаётся внутренний модуль, который:
Позволяет распределять значения между множеством элементов:
delay: 'stagger(100, 0)'
Это тоже отдельный модуль, который:
Модули взаимодействуют через:
onStart, onUpdate,
onComplete)Важно, что связь остаётся слабой:
Каждый модуль проходит несколько этапов:
1. Инициализация
2. Подготовка
3. Запуск
4. Обновление
5. Завершение
mo.js позволяет создавать собственные модули, используя базовые классы.
Пример кастомного модуля:
class CustomTween extends mojs.Tween {
constructor(options) {
super(options);
}
_update(progress) {
// кастомная логика
}
}
Возможности расширения:
Даже параметры в mo.js рассматриваются как мини-модули:
x: { 0: 200, easing: 'cubic.out' }
Здесь:
Пример объединения:
const shape = new mojs.Shape({ radius: { 0: 50 } });
const burst = new mojs.Burst({ count: 5 });
const timeline = new mojs.Timeline()
.add(shape, burst)
.play();
Здесь:
Сильная связность
Избыточная логика в одном модуле
Игнорирование Timeline
Неправильное использование параметров
Структура проекта:
animations/
shapes/
bursts/
timelines/
utils/
Каждый файл:
Пример:
// shapes/circle.js
export const createCircle = () =>
new mojs.Shape({
shape: 'circle',
radius: { 0: 50 }
});
const shape = new mojs.Shape({
onComplete() {
console.log('done');
}
});
События позволяют:
Модульная система mo.js представляет собой:
Такой подход делает библиотеку мощным инструментом для построения сложных анимационных систем с минимальной связностью и высокой гибкостью.