Анимации
Выбор технологий
Анимации часто используются для улучшения пользовательского интерфейса приложений. Современные браузеры хорошо поддерживают CSS-анимации, и существует множество различных библиотек, предоставляющих быстрые анимации на основе JavaScript. Также разрабатывается Web API и polyfill для тех, кто хочет использовать передовые технологии.
Mithril.js не предоставляет собственных API для анимации, поскольку существующие решения более чем достаточны для создания сложных и эффектных анимаций. Однако Mithril.js предлагает хуки (hooks), упрощающие работу в тех случаях, когда традиционно сложно реализовать анимацию.
Анимация при создании элемента
Анимация элемента при создании с использованием CSS реализуется очень просто. Просто добавьте анимацию к CSS-классу, как обычно:
.fancy {
animation: fade-in 0.5s;
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
var FancyComponent = {
view: function () {
return m('.fancy', 'Hello world');
},
};
m.mount(document.body, FancyComponent);
Анимация при удалении элемента
Проблема с анимацией перед удалением элемента заключается в необходимости дождаться завершения анимации, прежде чем фактически удалить элемент. К счастью, Mithril.js предлагает хук onbeforeremove
, позволяющий отложить удаление элемента.
Создадим exit
анимацию, которая изменяет opacity
от 1 до 0.
.exit {
animation: fade-out 0.5s;
}
@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
Теперь создадим простой компонент, который показывает и скрывает FancyComponent
, созданный в предыдущем разделе:
var on = true;
var Toggler = {
view: function () {
return [
m(
'button',
{
onclick: function () {
on = !on;
},
},
'Toggle'
),
on ? m(FancyComponent) : null,
];
},
};
Далее, изменим FancyComponent
, чтобы он исчезал при удалении:
var FancyComponent = {
onbeforeremove: function (vnode) {
vnode.dom.classList.add('exit');
return new Promise(function (resolve) {
vnode.dom.addEventListener('animationend', resolve);
});
},
view: function () {
return m('.fancy', 'Hello world');
},
};
vnode.dom
указывает на корневой DOM-элемент компонента (<div class="fancy">
). Здесь мы используем API classList
, чтобы добавить класс exit
к <div class="fancy">
.
Когда из onbeforeremove
возвращается Promise, Mithril.js ждет его разрешения и только после этого удаляет элемент. В этом случае он ждет завершения анимации исчезновения.
Чтобы убедиться в работоспособности анимаций появления и исчезновения, смонтируем компонент Toggler
.
m.mount(document.body, Toggler);
Обратите внимание, что хук onbeforeremove
срабатывает только на элементе, который теряет свой parentNode
при отсоединении от DOM. Это поведение реализовано намеренно. Оно предотвращает нежелательное поведение, когда при смене маршрута запускаются все анимации исчезновения на странице. Если анимация исчезновения не запускается, убедитесь, что обработчик onbeforeremove
привязан к элементу, расположенному как можно выше в DOM-дереве, чтобы гарантировать вызов кода анимации.
Производительность
При создании анимаций рекомендуется использовать только CSS-правила opacity
и transform
, поскольку они могут быть аппаратно ускорены современными браузерами и обеспечивают лучшую производительность, чем анимация свойств top
, left
, width
и height
.
Также рекомендуется избегать правила box-shadow
и селекторов, таких как :nth-child
, поскольку это также требует значительных вычислительных ресурсов. Если вы хотите анимировать box-shadow
, рассмотрите возможность размещения правила box-shadow
на псевдоэлемент и анимируйте прозрачность псевдоэлемента. К другим факторам, негативно влияющим на производительность, относятся большие или динамически масштабируемые изображения и перекрывающиеся элементы с разными значениями position
(например, элемент с position: absolute
над элементом с position: fixed
).