mo.js: создание красивых веб‑анимаций из кода
Что вы получите из этой статьи
- Пошаговый пример проекта в CodePen: от настроек до готовых визуальных эффектов.
- Подробные объяснения ключевых свойств mo.js (Shape, Burst, easing, stagger, generate и др.).
- Полный рабочий набор объектов и обработчик кликов, который можно скопировать и адаптировать.
- Практические дополнения: чек‑листы для ролей, критерии приёмки, тест‑кейсы, альтернативы и рекомендации по совместимости.
Введение
Если вы хотите оживить сайт — анимация помогает подчеркнуть интерфейс, привлечь внимание и добавить интерактивность. Можно использовать GIF, After Effects, Lottie или рисовать всё вручную в Canvas/WebGL, но для быстрых декоративных и интерактивных эффектов отличным выбором будет библиотека mo.js.
Определение: mo.js — JavaScript‑библиотека для создания motion‑graphics в браузере. Кратко: легкая, декларативная, ориентированная на векторные простые формы и наборы «взрывов» (bursts).
Важно: пример в статье ориентирован на работу в CodePen, но код легко переносится в любой сборщик/проекты без изменения логики.

Альт: Пример результата — разноцветные вспышки и геометрические фигуры, созданные с помощью mo.js.
Начало работы: настройка проекта в CodePen
- Создайте новый Pen в CodePen.
- Откройте Настройки (иконка в правом верхнем углу) и перейдите на вкладку JavaScript.
- В качестве препроцессора JavaScript выберите Babel — это даст поддержку современных возможностей JS и позволит писать код в удобном стиле.
- В разделе «Add External Scripts/Pens» найдите и подключите библиотеку mo.js.
- Нажмите Save and Close.
Примечание: можно работать и в локальном редакторе (VS Code). Тогда подключите mo.js через npm или CDN в вашем HTML.
Альт: Окно настроек CodePen, вкладка JavaScript, где подключается внешний скрипт mo.js.
Структура проекта и базовые стили
Давайте сменим фон, чтобы эффекты были виднее. В CSS‑панели добавьте:
body{
background: rgba(11,11,11,1);
}Важно: используйте тёмный фон для демонстрации светящихся объектов — так визуальный результат будет более плотным для глаза.
Базовые фигуры (Shape)
Создание объекта Shape — фундаментальный шаг. В JS‑панели напишите:
const redCirc = new mojs.Shape({
isShowStart: true
});Пояснение: const redCirc — переменная, new mojs.Shape создаёт объект. Параметр isShowStart:true заставляет фигуру появиться сразу при инициализации.
Если вы хотите сменить форму по умолчанию (круг) — укажите свойство shape:
const redCirc = new mojs.Shape({
isShowStart: true,
shape: 'rect'
});Чтобы задать обводку без заливки и анимацию радиуса и прозрачности:
const redCirc = new mojs.Shape({
isShowStart: true,
stroke: 'red',
strokeWidth: 5,
fill: 'none',
radius: 15
});Затем добавим анимацию, изменяя radius и opacity по времени:
const redCirc = new mojs.Shape({
isShowStart: true,
stroke: 'red',
strokeWidth: 5,
fill: 'none',
radius: {15:30},
opacity: {1:0},
duration: 1000
}).play();Пояснение: {15:30} и {1:0} — Delta‑объекты, указывающие стартовые и конечные значения. duration в миллисекундах.
Важно: .play() запускает анимацию один раз при создании объекта.
Управление порядком и easing
Чтобы задать последовательность анимаций используйте .then(). Пример:
const redCirc = new mojs.Shape({
isShowStart: true,
stroke: 'red',
strokeWidth: 5,
fill: 'none',
radius: 15,
duration: 1000
}).then({
strokeWidth: 0,
scale: {1: 2, easing: 'sin.in'},
duration: 500
}).play();Пояснение: easing задаёт кривую перехода. mo.js содержит набор предопределённых easing (‘sin.in’, ‘quad.out’, ‘cubic.out’ и т.д.).
Совет: для визуального выбора кривых используйте ресурс easings.net.
Burst — «взрыв» дочерних объектов
Burst — коллекция дочерних фигур, которые испускаются из одной точки.
Минимальный пример:
const sparks = new mojs.Burst({
}).play();Добавим радиус и угол вращения:
const sparks = new mojs.Burst({
radius: {0:30, easing: 'cubic.out'},
angle: {0: 90, easing: 'quad.out'}
}).play();Контроль дочерних свойств через children:
const sparks = new mojs.Burst({
radius: {0:30, easing: 'cubic.out'},
angle: {0: 90, easing: 'quad.out'},
count: 50,
children: {
shape: 'cross',
stroke: 'white',
points: 12,
radius: 10,
fill: 'none',
angle: {0:360},
duration: 300
}
}).play();Пояснение: count — количество дочерних элементов. Children наследуют те же свойства, что и Shape.
Важно: если анимация должна запускаться при клике — не вызывайте .play() на этапе создания, используйте .replay() в обработчике клика.
Обработчик кликов — позиционирование и перезапуск
Добавим слушатель кликов по документу, чтобы анимации запускались в точке клика:
document.addEventListener('click', function(e) {
redCirc
.tune({ x: e.pageX, y: e.pageY })
.replay();
sparks
.tune({ x: e.pageX, y: e.pageY })
.replay();
});Пояснение: .tune() меняет свойства объекта перед повторным запуском, .replay() запускает анимацию с начала каждый раз.
Чтобы убрать стартовую анимацию в центре страницы, удалите isShowStart и .play() из создания объектов. Чтобы убрать смещение анимации относительно точки клика, добавьте в объекты left: 0, top: 0:
left: 0,
top: 0,Это делает позиционирование абсолютным относительно страницы и позволяет .tune({x,y}) точно помещать анимацию в координаты клика.
Альт: Демонстрация клика мыши и вспышек в точке клика.
Психоделические треугольники и медленные вращения
Добавим большой burst с полигонами (треугольниками), задав массив цветов и сильный угол вращения:
const triangles = new mojs.Burst({
radius: {0: 1000, easing: 'cubic.out'},
angle: {1080: 0, easing: 'quad.out'},
left: 0, top: 0,
count: 20,
children: {
shape: 'polygon',
points: 3,
radius: {10: 100},
fill: ['red','yellow','blue','green'],
duration: 3000
}
});Пояснение: shape: ‘polygon’ + points: 3 создают треугольники. Массив fill задаёт цикл цветов.
Пятиугольники и задержки
Похожий burst, но с пятиугольниками и задержкой:
const pentagons = new mojs.Burst({
radius: {0: 1000, easing: 'cubic.out'},
angle: {0: 720, easing: 'quad.out'},
left: 0, top: 0,
count: 20,
children: {
shape: 'polygon',
radius: {1: 300},
points: 5,
fill: ['purple','pink','yellow','green'],
delay: 500,
duration: 3000
}
});Идея: delay заставляет pentagons появляться позже, создавая композицию поверх triangles.
Случайность: rand и generate
mo.js поддерживает встроенную генерацию случайных значений через выражения ‘rand(min, max)’. Пример:
const redSparks = new mojs.Burst({
left: 0, top: 0,
count: 8,
radius: {150: 350},
angle: {0: 90, easing: 'cubic.out'},
children: {
shape: 'line',
stroke: {'red':'transparent'},
strokeWidth: 5,
scaleX: {0.5:0},
degreeShift: 'rand(-90, 90)',
radius: 'rand(20, 300)',
duration: 500,
delay: 'rand(0, 150)'
}
});Важно: поскольку значения случайные, при каждом запуске надо вызывать .generate() перед .replay():
redSparks
.tune({ x: e.pageX, y: e.pageY })
.replay()
.generate();.generate() обновляет случайные параметры, иначе они были бы вычислены один раз при инициализации.
Stagger — ступенчатая задержка
Чтобы создавать последовательные эмиссии дочерних элементов, используйте stagger():
const lines = new mojs.Burst({
radius: {0: 1000, easing: 'cubic.out'},
angle: {0: 1440, easing: 'cubic.out'},
left: 0, top: 0,
count: 50,
children: {
shape: 'line',
radius: {1: 100, easing: 'elastic.out'},
fill: 'none',
stroke: ['red','orange'],
delay: 'stagger(10)',
duration: 1000
}
});stagger(10) добавляет 10 мс между эмиссиями соседних дочерних элементов.
Умные квадраты и сложные геометрии
Пример с прямоугольниками и изменяющейся шириной обводки:
const redSquares = new mojs.Burst({
radius: {0: 1000, easing: 'cubic.out'},
angle: {360: 0, easing: 'quad.out'},
left: 0, top: 0,
count: 20,
children: {
shape: 'rect',
radiusX: {1: 1000},
radiusY: 50,
points: 5,
fill: 'none',
stroke: {'red':'orange'},
strokeWidth: {5:15},
delay: 1000,
duration: 3000
}
});Этот объект показывает, как сочетать асимметричные размеры (radiusX, radiusY) и анимацию strokeWidth для декоративных эффектов.
Полный пример: собранный код для Pen
Ниже — скомпилированный набор объектов и обработчик клика (убедитесь, что все объекты добавлены в обработчик клика):
// Примеры объектов
const redCirc = new mojs.Shape({
left: 0, top: 0,
stroke: 'red',
strokeWidth: 5,
fill: 'none',
radius: {15:30},
opacity: {1:0},
duration: 1000
});
const sparks = new mojs.Burst({
left: 0, top: 0,
radius: {0:30, easing: 'cubic.out'},
angle: {0: 90, easing: 'quad.out'},
count: 50,
children: {
shape: 'cross',
stroke: 'white',
points: 12,
radius: 10,
fill: 'none',
angle: {0:360},
duration: 300
}
});
const triangles = new mojs.Burst({
left: 0, top: 0,
radius: {0: 1000, easing: 'cubic.out'},
angle: {1080: 0, easing: 'quad.out'},
count: 20,
children: {
shape: 'polygon',
points: 3,
radius: {10: 100},
fill: ['red','yellow','blue','green'],
duration: 3000
}
});
const pentagons = new mojs.Burst({
left: 0, top: 0,
radius: {0: 1000, easing: 'cubic.out'},
angle: {0: 720, easing: 'quad.out'},
count: 20,
children: {
shape: 'polygon',
radius: {1: 300},
points: 5,
fill: ['purple','pink','yellow','green'],
delay: 500,
duration: 3000
}
});
const redSparks = new mojs.Burst({
left: 0, top: 0,
count: 8,
radius: {150: 350},
angle: {0: 90, easing: 'cubic.out'},
children: {
shape: 'line',
stroke: {'red':'transparent'},
strokeWidth: 5,
scaleX: {0.5:0},
degreeShift: 'rand(-90, 90)',
radius: 'rand(20, 300)',
duration: 500,
delay: 'rand(0, 150)'
}
});
const lines = new mojs.Burst({
left: 0, top: 0,
radius: {0: 1000, easing: 'cubic.out'},
angle: {0: 1440, easing: 'cubic.out'},
count: 50,
children: {
shape: 'line',
radius: {1: 100, easing: 'elastic.out'},
fill: 'none',
stroke: ['red','orange'],
delay: 'stagger(10)',
duration: 1000
}
});
const redSquares = new mojs.Burst({
left: 0, top: 0,
radius: {0: 1000, easing: 'cubic.out'},
angle: {360: 0, easing: 'quad.out'},
count: 20,
children: {
shape: 'rect',
radiusX: {1: 1000},
radiusY: 50,
points: 5,
fill: 'none',
stroke: {'red':'orange'},
strokeWidth: {5:15},
delay: 1000,
duration: 3000
}
});
// Обработчик кликов — не забудьте вызвать .generate() для объектов с rand
document.addEventListener('click', function(e) {
[redCirc, sparks, triangles, pentagons, lines, redSquares].forEach(obj => {
obj.tune({ x: e.pageX, y: e.pageY }).replay();
});
// redSparks использует rand() — заново вычисляем значения
redSparks.tune({ x: e.pageX, y: e.pageY }).replay().generate();
});Этот код — готовая основа для творческой работы. Копируйте в свой Pen или локальный проект и экспериментируйте с параметрами.
Паттерны использования и рекомендации по производительности
- Ограничивайте количество одновременных анимаций на странице, особенно на мобильных устройствах.
- Используйте простые формы (line, rect, polygon) вместо сложных SVG, если эффект рассчитан только на декоративность.
- Для крупных сцен с тысячами элементов лучше выбирать WebGL/Canvas/Three.js, а не DOM‑ или SVG‑рекурсии.
- Кэшируйте значения, которые не меняются между запусками (например, массивы цветов).
Важно: тестируйте на целевых устройствах (мобильные, слабые ноутбуки). Анимации с большим количеством элементов могут нагружать CPU и вызывать просадки кадров.
Когда mo.js не подходит — контрпример
- Если вам нужен сложный сценографический монтаж с таймлайном, масками и аудио‑синхронизацией — выбирайте After Effects + Lottie (Bodymovin) или WebGL решения.
- Для анимации UI‑элементов (переходы между страницами, layout‑адаптация) часто лучше подходят CSS‑трансформации и фреймворки типа GSAP, которые имеют мощные плагины для сцен и сложной последовательности.
- Если нужно рендерить тысячи отдельных частиц при 60 fps — Canvas/WebGL дадут лучший результат.
Альтернативы и сравнение (коротко)
- GSAP — мощный, оптимизированный, коммерческие плагины; отлично подходит для сложных последовательностей.
- Anime.js — лёгкая библиотека, удобна для path/transform анимаций.
- Lottie — экспорт из After Effects в JSON, идеален для сложной графики из дизайнера.
- CSS animations — нативно, быстро, для простых переходов и состояний UI.
Выбор зависит от требований: гибкость дизайна, производительность, сложность анимации и интеграция с командой дизайнеров.
Чек‑лист перед выпуском на прод
Для разработчика:
- Проверить производительность на целевых устройствах.
- Убедиться, что числа duration/ delay / count адекватны для мобильных.
- Отключить .play() при создании, если анимация должна запускаться только при событии.
Для дизайнера:
- Согласовать цвета и ширины stroke.
- Проверить, что анимация не мешает читаемости контента.
Для менеджера проекта:
- Оценить влияние на метрики (time to interactive, CLS).
Критерии приёмки
- Анимация запускается в точке клика и не смещается (left/top = 0; tune x/y).
- На большинстве тестовых устройств (список: iPhone 8+, Android среднего сегмента, настольный) рендер ≥ 30 fps при типичной нагрузке.
- Нет утечек памяти при длительном использовании (навешенные слушатели и объекты очищаются при необходимости).
- Доступность: анимация не нарушает взаимодействие с основным UI.
Сценарии тестирования и тест‑кейсы
Тест 1 — запуск при клике:
- Действие: клик в центре, в углу, быстро несколько кликов подряд.
- Ожидаемый результат: анимация появляется в точке клика, каждая новая анимация запускается корректно.
Тест 2 — производительность:
- Действие: многократный массовый запуск анимации (10–20 раз подряд).
- Ожидаемый результат: частота кадров остаётся на приемлемом уровне, браузер не зависает.
Тест 3 — адаптивность:
- Действие: открыть на мобильном и на десктопе.
- Ожидаемый результат: корректное масштабирование и отсутствие сильных лагов на мобильных.
Тест 4 — доступность:
- Действие: проверка, что анимация не мешает клавиатурной навигации и фокусируемым элементам.
- Ожидаемый результат: основные элементы остаются доступными.
Роли и чек‑листы
Дизайнер:
- Подготовить палитру и вариант в PSD/Sketch/FIGMA.
- Уточнить желаемые easing и длительность.
Front‑end разработчик:
- Интегрировать mo.js через CDN или npm.
- Обеспечить отключение для слабых устройств (feature flag).
QA инженер:
- Прогнать тест‑кейсы по производительности и доступности.
Шпаргалка (cheat sheet) по свойствам mo.js
- radius: {start:end} — радиус/размер.
- stroke / fill — цвета.
- strokeWidth — ширина обводки.
- duration — длительность в мс.
- delay — задержка в мс или stagger/ rand.
- easing — кривая (sin.in, quad.out, cubic.out и др.).
- left, top — положение базовой точки (0/0 отключает центрировку).
- count — количество дочерних объектов в Burst.
- children — объект с параметрами для каждого ребёнка.
- .tune({x,y}) — переносит объект.
- .play(), .replay() — запуск/повтор.
- .generate() — пересчитать rand() выражения.
Ментальные модели и эвристики
- Подумайте об анимации как о кратковременном событии (импульс — burst) или как о продолжительном элементе (loop) — mo.js лучше подходит к первому.
- Используйте задержки и stagger для создания ретроперспективы: маленькие задержки между похожими объектами создают сложное ощущение движения, не требуя большого числа объектов.
- Делайте случайность контролируемой: рандом для углов или радиусов хорош, когда результат всё ещё эстетичен.
Совместимость и миграции
- mo.js работает в современных браузерах. Если нужна поддержка старых IE — возможны проблемы; проверяйте transpile через Babel.
- Для миграции с CSS‑анимаций: переносите логику в mo.js постепенно, сначала для декоративных элементов.
- Для интеграции с фреймворками (React/Vue): создавайте обёртки компонентов, инициализируйте mo.js в хуках жизненного цикла и очищайте слушатели при unmount.
Пример (React, упрощённо):
useEffect(() => {
const burst = new mojs.Burst({ /* параметры */ });
const handler = (e) => { burst.tune({x: e.pageX, y: e.pageY }).replay(); };
document.addEventListener('click', handler);
return () => {
document.removeEventListener('click', handler);
// при необходимости удалять объекты/очищать ссылки
};
}, []);Безопасность и конфиденциальность
- mo.js работает на клиенте и не передаёт данные на сервер сам по себе. Если вы отправляете координаты пользовательских кликов на сервер — убедитесь, что это действительно нужно и соблюдается политика конфиденциальности.
- Для анимаций, зависящих от пользовательских данных, уточняйте соответствие GDPR/LPD: не храните и не передавайте лишние персональные данные.
Дерево решений — какую технологию выбрать
flowchart TD
A[Нужна анимация на сайте?] --> B{Тип анимации}
B --> |Декоративные, реакция на клики| C[mo.js]
B --> |UI‑переходы, формы| D[CSS / GSAP]
B --> |Экспорт из дизайнера| E[Lottie]
B --> |Тысячи частиц, 3D| F[Canvas / WebGL]
C --> G[Умеренная нагрузка, быстрая реализация]
D --> H[Высокая точность UI]
E --> I[Сложные векторные анимации из AE]
F --> J[Максимальная производительность]Короткая методология творческого цикла
- Прототип: быстро собрать в CodePen базовые Shape/Burst.
- Итерация: менять radius, duration, easing, count до желаемого результата.
- Тесты: профилировать на мобильных, проверять fps.
- Интеграция: вставлять в проект как компонент, обеспечить feature flag.
- Мониторинг: наблюдать метрики производительности после релиза.
Примеры типичных проблем и их решения
Проблема: анимация запускается в центре страницы, а не в точке клика. Решение: уберите isShowStart и .play(), добавьте left:0, top:0 и используйте .tune({x,y}).
Проблема: случайные параметры повторяются одинаково при каждом клике. Решение: вызовите .generate() перед .replay() для объектов с rand().
Проблема: низкий FPS на мобильных. Решение: уменьшите count, упростите children, уменьшите длительности и сложность easing.
Глоссарий (однострочные объяснения)
- Shape — базовый геометрический объект mo.js.
- Burst — коллекция дочерних объектов, испускаемая из точки.
- Delta‑объект — запись вида {start:end} для анимируемого свойства.
- tune() — метод для временного изменения свойств перед воспроизведением.
- replay() — перезапуск анимации с начала.
- generate() — пересчёт rand() выражений.
Итог и рекомендации
mo.js — отличный инструмент для быстрого создания декоративных, интерактивных эффектов на веб‑страницах. Он прост в освоении, декларативен и даёт большие возможности по композиции визуальных эффектов без тяжелой логики. Для боевых проектов придерживайтесь принципов оптимизации и тестирования, описанных выше.
Важно: начинайте с малого — один burst, один listener — и шаг за шагом усложняйте сцену.
Альт: Итоговая композиция со всеми вспышками и геометрическими фигурами, собранная из примеров в статье.
Полезные ссылки и ресурсы
- Официальный сайт mo.js: репозиторий и документация (поиск через вашу поисковую систему).
- easings.net — визуализация кривых easing.
Вдохновляйтесь, экспериментируйте и помните: в творчестве часто случаются приятные неожиданные результаты.
Похожие материалы
Сохранение и восстановление значков Windows
Как открыть HEVC и HEIF на Windows 11 бесплатно
Ограничить доступ приложений к данным в Facebook
Как скрыть статус в сети в Facebook
Как включить и использовать почерк в Gboard