Библиотека mo.js представляет собой модульный инструмент для создания анимаций, работающий поверх JavaScript и использующий декларативный подход к описанию движения. В контексте Vanilla JavaScript она подключается без сборщиков и дополнительных зависимостей.
<script src="https://cdn.jsdelivr.net/npm/@mojs/core"></script>
После подключения глобальный объект mojs становится
доступным в области видимости браузера.
<!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 построена вокруг нескольких ключевых сущностей:
Tween — базовая единица анимации, описывающая изменение параметров во времени Timeline — последовательность или группа анимаций Shape — геометрические примитивы (круги, линии, многоугольники) Burst — набор частиц, распространяющихся из точки Html — анимация DOM-элементов
Каждая сущность описывается через объект конфигурации, где задаются параметры:
Tween используется для анимации числовых значений и CSS-свойств.
const tween = new mojs.Tween({
duration: 1000,
onUpdate(progress) {
console.log(progress);
}
});
tween.play();
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 позволяет создавать визуальные элементы, основанные на SVG.
const circle = new mojs.Shape({
shape: 'circle',
fill: 'none',
stroke: 'red',
strokeWidth: 4,
radius: 40,
duration: 1000
});
circle.play();
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 используется для создания эффектов взрыва, вспышек и рассеивания элементов.
const burst = new mojs.Burst({
radius: { 0: 100 },
count: 10,
children: {
shape: 'circle',
fill: 'orange',
radius: 5,
duration: 1000
}
});
burst.play();
Burst состоит из родительского объекта и дочерних элементов:
const burst = new mojs.Burst({
radius: { 0: 120 },
count: 6,
children: {
shape: 'line',
stroke: 'white',
strokeWidth: 2,
degreeShift: 'rand(0, 360)',
duration: 900
}
});
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 определяет характер изменения параметров во времени.
const shape = new mojs.Shape({
shape: 'circle',
radius: { 0: 50 },
duration: 1000,
easing: 'cubic.out'
});
shape.play();
const shape = new mojs.Shape({
shape: 'circle',
radius: { 0: 60 },
duration: 1200,
easing: 'elastic.out'
});
Html-модуль позволяет анимировать реальные элементы интерфейса.
const el = document.querySelector('.button');
const anim = new mojs.Html({
el: el,
x: { 0: 100 },
opacity: { 1: 0.5 },
duration: 800
});
anim.play();
Каждая анимация поддерживает события:
onStartonUpdateonCompleteconst 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, однако сложные сцены требуют контроля нагрузки.
Рекомендации по оптимизации:
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)'
Shape и Burst используют SVG как базовую технологию рендеринга, что позволяет:
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();
});