W zaawansowanych systemach NOVA LAB potrzebujemy wyrafinowanych efektów — kaskadowe ładowanie elementów dashboardu, animacja przy pierwszym wyświetleniu strony, precyzyjna kontrola czasów trwania i szacunek dla preferencji użytkowników dotyczących ruchu. Poznaj wzorce, które nadają interfejsom profesjonalny charakter.
Domyślnie
<Transition> animuje element tylko przy przełączeniu v-if/v-show. Atrybut appear powoduje, że animacja uruchomi się również przy pierwszym renderowaniu (mount) komponentu:1<Transition appear name="fade">
2 <div>Ten element animuje się przy załadowaniu strony</div>
3</Transition>To idealne rozwiązanie dla elementów widocznych od razu po załadowaniu — logo stacji, nagłówek dashboardu, panel statusu. Bez
appear te elementy po prostu "byłyby tam" bez żadnej animacji wejścia.Możesz użyć specjalnych klas CSS dla animacji appear (niezależnych od normalnych klas enter):
1<Transition
2 appear
3 appear-from-class="appear-start"
4 appear-active-class="appear-running"
5 appear-to-class="appear-end"
6>
7 <div>Custom appear animation</div>
8</Transition>Lub z bibliotekami:
1<Transition
2 appear
3 appear-active-class="animate__animated animate__fadeInDown"
4>
5 <header>NOVA LAB Control Center</header>
6</Transition>Jeden z najbardziej efektownych wzorców — kaskadowe pojawianie się elementów listy, gdzie każdy kolejny element pojawia się z rosnącym opóźnieniem. Wygląda jak wyświetlanie danych na holograficznym dashboardzie NOVA LAB, element po elemencie:
1<TransitionGroup
2 appear
3 :css="false"
4 @before-enter="onBeforeEnter"
5 @enter="onEnter"
6 tag="div"
7>
8 <div v-for="(item, index) in items" :key="item.id" :data-index="index">
9 {{ item.name }}
10 </div>
11</TransitionGroup>Kluczem jest atrybut
:data-index — przekazuje indeks elementu do hooka JS, który oblicza opóźnienie:1function onBeforeEnter(el) {
2 el.style.opacity = 0
3 el.style.transform = 'translateY(20px)'
4}
5
6function onEnter(el, done) {
7 // Każdy kolejny element ma o 150ms większe opóźnienie
8 const delay = el.dataset.index * 150
9
10 setTimeout(() => {
11 el.style.transition = 'all 0.5s ease'
12 el.style.opacity = 1
13 el.style.transform = 'translateY(0)'
14 el.addEventListener('transitionend', done, { once: true })
15 }, delay)
16}Efekt: element 0 pojawia się natychmiast, element 1 po 150ms, element 2 po 300ms itd. Dla 10 elementów cała animacja trwa 1.5s + 0.5s (czas samej animacji) = ~2s.
Wskazówka: Ogranicz opóźnienie do max ~1s, aby użytkownik nie czekał zbyt długo na ostatnie elementy:
1const delay = Math.min(el.dataset.index * 100, 1000)Gdy element ma zarówno CSS transition jak i animation, lub gdy zagnieżdżone elementy mają różne czasy animacji, Vue może nie wykryć prawidłowego momentu zakończenia. Atrybut
:duration pozwala jawnie określić czas trwania w milisekundach:1<!-- Jednolity czas dla wejścia i wyjścia -->
2<Transition :duration="500">...</Transition>
3
4<!-- Różne czasy dla wejścia i wyjścia -->
5<Transition :duration="{ enter: 300, leave: 500 }">...</Transition>Jest to szczególnie przydatne gdy:
Szanuj ustawienia użytkownika dotyczące ruchu. Osoby z zaburzeniami przedsionkowymi lub epilepsją mogą mieć włączoną preferencję
prefers-reduced-motion. Twój CSS powinien to respektować:1/* Normalne animacje */
2.fade-enter-active,
3.fade-leave-active {
4 transition: opacity 0.3s ease, transform 0.3s ease;
5}
6
7.fade-enter-from,
8.fade-leave-to {
9 opacity: 0;
10 transform: translateY(10px);
11}
12
13/* Wyłącz animacje dla użytkowników, którzy ich nie chcą */
14@media (prefers-reduced-motion: reduce) {
15 .fade-enter-active,
16 .fade-leave-active {
17 transition: none;
18 }
19
20 .fade-enter-from,
21 .fade-leave-to {
22 opacity: 1;
23 transform: none;
24 }
25}Możesz też obsłużyć to w JavaScript:
1const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
2
3function onEnter(el, done) {
4 if (prefersReducedMotion) {
5 done() // Pomiń animację
6 return
7 }
8 // Normalna animacja...
9}Animuj tylko
i transform
— te właściwości są akcelerowane przez GPU i nie powodują reflow/repaint. Unikaj animowania opacity
width, height, top, left, margin, padding.Używaj
dla ciężkich animacji — informuje przeglądarkę o nadchodzącej animacji, pozwalając na optymalizację:will-change
1.heavy-animation-enter-active {
2 will-change: transform, opacity;
3 transition: all 0.5s ease;
4}Preferuj CSS nad JS — CSS animations są optymalizowane przez przeglądarkę i działają na osobnym wątku. Używaj JS hooków tylko gdy potrzebujesz dynamicznych wartości.
Krótkie czasy trwania — animacje UI powinny trwać 200-500ms. Dłuższe animacje spowalniają interakcję i irytują użytkowników.
Testuj na urządzeniach mobilnych — animacje, które działają płynnie na desktopie, mogą lagować na starszych telefonach.