Гид по технологиям

mo.js: создание красивых веб‑анимаций из кода

10 min read Frontend Обновлено 22 Dec 2025
mo.js: создание веб‑анимаций из кода
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

Альт: Пример результата — разноцветные вспышки и геометрические фигуры, созданные с помощью mo.js.

Начало работы: настройка проекта в CodePen

  1. Создайте новый Pen в CodePen.
  2. Откройте Настройки (иконка в правом верхнем углу) и перейдите на вкладку JavaScript.
  3. В качестве препроцессора JavaScript выберите Babel — это даст поддержку современных возможностей JS и позволит писать код в удобном стиле.
  4. В разделе «Add External Scripts/Pens» найдите и подключите библиотеку mo.js.
  5. Нажмите Save and Close.

Примечание: можно работать и в локальном редакторе (VS Code). Тогда подключите mo.js через npm или CDN в вашем HTML.

CodePen — настройки JavaScript и подключение внешних скриптов

Альт: Окно настроек 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).

Критерии приёмки

  1. Анимация запускается в точке клика и не смещается (left/top = 0; tune x/y).
  2. На большинстве тестовых устройств (список: iPhone 8+, Android среднего сегмента, настольный) рендер ≥ 30 fps при типичной нагрузке.
  3. Нет утечек памяти при длительном использовании (навешенные слушатели и объекты очищаются при необходимости).
  4. Доступность: анимация не нарушает взаимодействие с основным 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[Максимальная производительность]

Короткая методология творческого цикла

  1. Прототип: быстро собрать в CodePen базовые Shape/Burst.
  2. Итерация: менять radius, duration, easing, count до желаемого результата.
  3. Тесты: профилировать на мобильных, проверять fps.
  4. Интеграция: вставлять в проект как компонент, обеспечить feature flag.
  5. Мониторинг: наблюдать метрики производительности после релиза.

Примеры типичных проблем и их решения

Проблема: анимация запускается в центре страницы, а не в точке клика. Решение: уберите 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

Альт: Итоговая композиция со всеми вспышками и геометрическими фигурами, собранная из примеров в статье.

Полезные ссылки и ресурсы

  • Официальный сайт mo.js: репозиторий и документация (поиск через вашу поисковую систему).
  • easings.net — визуализация кривых easing.

Вдохновляйтесь, экспериментируйте и помните: в творчестве часто случаются приятные неожиданные результаты.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Сохранение и восстановление значков Windows
Windows

Сохранение и восстановление значков Windows

Как открыть HEVC и HEIF на Windows 11 бесплатно
Windows

Как открыть HEVC и HEIF на Windows 11 бесплатно

Ограничить доступ приложений к данным в Facebook
Конфиденциальность

Ограничить доступ приложений к данным в Facebook

Как скрыть статус в сети в Facebook
Приватность

Как скрыть статус в сети в Facebook

Как включить и использовать почерк в Gboard
Мобильные

Как включить и использовать почерк в Gboard

Исчезающие сообщения в Instagram — Vanish Mode
Социальные сети

Исчезающие сообщения в Instagram — Vanish Mode