Animacje
Wybór technologii
Animacje są często wykorzystywane do ożywienia interfejsu aplikacji. Współczesne przeglądarki oferują dobre wsparcie dla animacji CSS. Dostępne są również różne biblioteki JavaScript, które umożliwiają tworzenie szybkich animacji. Dla osób preferujących najnowsze rozwiązania, istnieje rozwijające się Web API oraz polyfill.
Mithril.js nie dostarcza własnych API do animacji, ponieważ istniejące opcje są wystarczające do tworzenia bogatych i złożonych efektów. Mithril.js udostępnia jednak hooki, które ułatwiają implementację animacji w specyficznych przypadkach, gdzie tradycyjne podejścia mogą być problematyczne.
Animacja podczas tworzenia elementu
Animowanie elementu CSS w momencie jego tworzenia jest bardzo proste. Wystarczy dodać animację do klasy 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);
Animacja podczas usuwania elementu
Problem z animowaniem elementu przed jego usunięciem polega na konieczności odczekania na zakończenie animacji, zanim element zostanie usunięty z DOM. Mithril.js udostępnia hook onbeforeremove
, który pozwala opóźnić usunięcie elementu do czasu zakończenia animacji.
Zdefiniujmy animację exit
, która zmienia przezroczystość (opacity
) z 1 na 0:
.exit {
animation: fade-out 0.5s;
}
@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
Stwórzmy przykładowy komponent, który wyświetla i ukrywa FancyComponent
z poprzedniej sekcji:
var on = true;
var Toggler = {
view: function () {
return [
m(
'button',
{
onclick: function () {
on = !on;
},
},
'Toggle'
),
on ? m(FancyComponent) : null,
];
},
};
Zmodyfikujmy FancyComponent
, aby zanikał podczas usuwania:
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
wskazuje na główny element DOM komponentu (<div class="fancy">
). Używamy API classList
, aby dodać klasę exit
do <div class="fancy">
.
Następnie zwracamy Promise, który zostanie rozwiązany po wywołaniu zdarzenia animationend
. Kiedy zwracamy Promise z onbeforeremove
, Mithril.js czeka na jego rozwiązanie, a dopiero potem usuwa element. W tym przypadku czeka na zakończenie animacji wyjścia.
Działanie animacji wejścia i wyjścia możemy sprawdzić, montując komponent Toggler
:
m.mount(document.body, Toggler);
Hook onbeforeremove
jest wywoływany tylko na elemencie, który traci swojego parentNode
, czyli gdy element jest odłączany od DOM. Takie zachowanie zapobiega sytuacji, w której każda animacja wyjścia na stronie uruchamiałaby się podczas zmiany routingu, co mogłoby być irytujące dla użytkownika. Jeśli animacja wyjścia nie działa, upewnij się, że dołączasz handler onbeforeremove
tak wysoko w hierarchii komponentów, jak to możliwe, aby zagwarantować, że kod animacji zostanie wywołany.
Wydajność
Podczas tworzenia animacji zaleca się używanie tylko reguł CSS opacity
i transform
, ponieważ mogą one być akcelerowane sprzętowo przez nowoczesne przeglądarki, co zapewnia lepszą wydajność niż animowanie właściwości top
, left
, width
i height
.
Zaleca się również unikanie reguły box-shadow
i selektorów takich jak :nth-child
, ponieważ są to opcje wymagające dużych zasobów obliczeniowych. Jeśli chcesz animować box-shadow
, rozważ umieszczenie reguły box-shadow
na pseudo elemencie i animowanie przezroczystości tego elementu. Inne potencjalnie kosztowne operacje to duże lub dynamicznie skalowane obrazy oraz nakładające się elementy z różnymi wartościami position
(np. element z pozycją absolute
na elemencie z pozycją fixed
).