Vanilla JavaScript

Библиотека mo.js представляет собой модульный инструмент для создания анимаций, работающий поверх JavaScript и использующий декларативный подход к описанию движения. В контексте Vanilla JavaScript она подключается без сборщиков и дополнительных зависимостей.

Подключение через CDN

<script src="https://cdn.jsdelivr.net/npm/@mojs/core"></script>

После подключения глобальный объект mojs становится доступным в области видимости браузера.

Базовая структура HTML

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <title>mo.js animation</title>
</head>
<body>

<button id="animate">Запуск</button>

<script src="https://cdn.jsdelivr.net/npm/@mojs/core"></script>
<script src="app.js"></script>

</body>
</html>

Базовая концепция анимационной модели mo.js

Архитектура mo.js построена вокруг нескольких ключевых сущностей:

Tween — базовая единица анимации, описывающая изменение параметров во времени Timeline — последовательность или группа анимаций Shape — геометрические примитивы (круги, линии, многоугольники) Burst — набор частиц, распространяющихся из точки Html — анимация DOM-элементов

Каждая сущность описывается через объект конфигурации, где задаются параметры:

  • длительность
  • задержка
  • easing-функция
  • начальные и конечные значения свойств

Простая анимация через Tween

Tween используется для анимации числовых значений и CSS-свойств.

const tween = new mojs.Tween({
  duration: 1000,
  onUpdate(progress) {
    console.log(progress);
  }
});

tween.play();

Анимация DOM через свойство onUpdate

const box = document.querySelector('.box');

const tween = new mojs.Tween({
  duration: 800,
  onUpdate(progress) {
    box.style.transform = `translateX(${progress * 300}px)`;
  }
});

tween.play();

Tween работает как низкоуровневый механизм, поверх которого строятся более сложные эффекты.


Геометрические анимации Shape

Shape позволяет создавать визуальные элементы, основанные на SVG.

const circle = new mojs.Shape({
  shape: 'circle',
  fill: 'none',
  stroke: 'red',
  strokeWidth: 4,
  radius: 40,
  duration: 1000
});

circle.play();

Основные параметры Shape

  • shape — тип фигуры (circle, rect, polygon, line)
  • radius — размер
  • stroke, fill — стилизация
  • strokeWidth — толщина линии
  • x, y — позиционирование
  • scale, opacity, angle — трансформации

Анимация трансформаций

const shape = new mojs.Shape({
  shape: 'rect',
  fill: 'blue',
  radius: 30,
  duration: 1200,
  scale: { 0: 1 },
  opacity: { 0: 1 }
});

shape.play();

Burst-анимации частиц

Burst используется для создания эффектов взрыва, вспышек и рассеивания элементов.

const burst = new mojs.Burst({
  radius: { 0: 100 },
  count: 10,
  children: {
    shape: 'circle',
    fill: 'orange',
    radius: 5,
    duration: 1000
  }
});

burst.play();

Структура Burst

Burst состоит из родительского объекта и дочерних элементов:

  • родитель управляет радиусом распространения
  • children описывает поведение частиц

Настройка траекторий

const burst = new mojs.Burst({
  radius: { 0: 120 },
  count: 6,
  children: {
    shape: 'line',
    stroke: 'white',
    strokeWidth: 2,
    degreeShift: 'rand(0, 360)',
    duration: 900
  }
});

Timeline и управление последовательностями

Timeline объединяет несколько анимаций в единый сценарий.

const circle = new mojs.Shape({
  shape: 'circle',
  radius: 30,
  fill: 'red',
  duration: 500
});

const square = new mojs.Shape({
  shape: 'rect',
  radius: 20,
  fill: 'blue',
  duration: 500,
  delay: 500
});

const timeline = new mojs.Timeline();

timeline.add(circle, square);

timeline.play();

Синхронизация анимаций

const timeline = new mojs.Timeline({
  repeat: 2
});

timeline.add([
  new mojs.Shape({
    shape: 'circle',
    radius: 20,
    duration: 600
  }),
  new mojs.Shape({
    shape: 'rect',
    radius: 15,
    duration: 600,
    delay: 300
  })
]);

timeline.play();

Easing и управление динамикой движения

Easing определяет характер изменения параметров во времени.

const shape = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 50 },
  duration: 1000,
  easing: 'cubic.out'
});

shape.play();

Основные типы easing

  • linear
  • quad.in / quad.out
  • cubic.in / cubic.out
  • elastic.out
  • bounce.out

Использование функции easing

const shape = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 60 },
  duration: 1200,
  easing: 'elastic.out'
});

Интеграция с DOM-элементами через mojs.Html

Html-модуль позволяет анимировать реальные элементы интерфейса.

const el = document.querySelector('.button');

const anim = new mojs.Html({
  el: el,
  x: { 0: 100 },
  opacity: { 1: 0.5 },
  duration: 800
});

anim.play();

Возможности Html-анимации

  • transform (translate, scale, rotate)
  • opacity
  • фильтры
  • синхронизация с другими mo.js объектами

Событийная модель и управление жизненным циклом

Каждая анимация поддерживает события:

  • onStart
  • onUpdate
  • onComplete
const shape = new mojs.Shape({
  shape: 'circle',
  radius: 40,
  duration: 1000,
  onStart() {
    console.log('start');
  },
  onComplete() {
    console.log('end');
  }
});

shape.play();

Контроль состояния

Анимации могут:

  • запускаться (play)
  • останавливаться (pause)
  • сбрасываться (replay)
shape.pause();
shape.play();
shape.replay();

Комбинирование эффектов

Сложные сцены формируются через объединение Burst, Shape и Timeline.

const circle = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 50 },
  fill: 'none',
  stroke: 'red',
  duration: 600
});

const burst = new mojs.Burst({
  radius: { 0: 80 },
  count: 8,
  children: {
    shape: 'circle',
    fill: 'yellow',
    radius: 4,
    duration: 800
  }
});

const timeline = new mojs.Timeline();
timeline.add(circle, burst);

document.addEventListener('click', () => {
  timeline.replay();
});

Работа с координатами и позиционированием

mo.js использует координатную систему относительно центра экрана или родительского контейнера.

const shape = new mojs.Shape({
  shape: 'circle',
  radius: 30,
  x: 200,
  y: 150
});

Относительное позиционирование

x: { 0: 100 },
y: { 0: -50 }

Производительность и оптимизация

Анимации mo.js оптимизированы под requestAnimationFrame, однако сложные сцены требуют контроля нагрузки.

Рекомендации по оптимизации:

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

Паттерны использования в интерфейсах

Клик-эффекты

const burst = new mojs.Burst({
  radius: { 0: 60 },
  count: 6,
  children: {
    shape: 'circle',
    fill: 'green',
    duration: 500
  }
});

document.addEventListener('click', (e) => {
  burst.tune({ x: e.pageX, y: e.pageY }).replay();
});

Интерактивные кнопки

const scale = new mojs.Tween({
  duration: 300,
  onUpdate(progress) {
    button.style.transform = `scale(${1 + progress * 0.2})`;
  }
});

button.addEventListener('mouseenter', () => scale.play());
button.addEventListener('mouseleave', () => scale.replay());

Управление группами анимаций

mo.js позволяет строить сложные системы анимаций через композицию объектов.

const timeline = new mojs.Timeline();

for (let i = 0; i < 5; i++) {
  timeline.add(
    new mojs.Shape({
      shape: 'circle',
      radius: 10 + i * 5,
      duration: 500 + i * 100,
      delay: i * 100
    })
  );
}

timeline.play();

Система параметров диапазонов

mo.js поддерживает динамические диапазоны значений:

const shape = new mojs.Shape({
  radius: { 10: 50 },
  opacity: { 0: 1 },
  duration: 1000
});

Также доступна генерация случайных значений:

degreeShift: 'rand(0, 360)'

Использование SVG как основы визуализации

Shape и Burst используют SVG как базовую технологию рендеринга, что позволяет:

  • масштабировать без потери качества
  • применять stroke-анимации
  • работать с векторной графикой напрямую
const line = new mojs.Shape({
  shape: 'line',
  stroke: 'black',
  strokeWidth: 3,
  duration: 700
});

Сложные сцены и синхронизация событий

const burst = new mojs.Burst({
  radius: { 0: 100 },
  count: 12,
  children: {
    shape: 'rect',
    fill: 'purple',
    duration: 800
  }
});

const shape = new mojs.Shape({
  shape: 'circle',
  radius: { 0: 40 },
  fill: 'transparent',
  stroke: 'purple',
  duration: 800
});

document.addEventListener('click', (e) => {
  const opts = { x: e.pageX, y: e.pageY };
  burst.tune(opts).replay();
  shape.tune(opts).replay();
});