7 marca 2025 (updated: 7 marca 2025)
Chapters
Animacje są niezbędne w dzisiejszym rozwoju stron internetowych, ponieważ podnoszą UX i jakość projektu. Dowiedz się o Framer Motion, potężnej bibliotece React do animacji.
Animacje są bardzo ważnym aspektem tworzenia nowoczesnych aplikacji internetowych, szczególnie jeśli chodzi o poprawę doświadczeń użytkowników lub przyciąganie uwagi do kluczowych części interfejsu aplikacji. Dobrze wykonane animacje poprawią jakość projektu, zwiększą jego atrakcyjność i ostatecznie sprawią, że użytkownicy będą wracać częściej. Jednak tworzenie animacji nie zawsze jest łatwe. W tym artykule dzielę się moim doświadczeniem z Framer Motion, otwartą biblioteką przyspieszającą tworzenie animacji w środowisku React.
Animacje można podzielić na kilka podstawowych typów:
Fade in/out - Animowany element staje się coraz bardziej widoczny/niewidoczny. Efekt ten często można zobaczyć podczas przewijania strony internetowej. Przykład animacji Fade in:
Slide in/out - Animowany element porusza się po ekranie. Animacje Slide in/out często są łączone z animacjami Fade in/out. Przykład animacji Slide in + Fade in:
Rotate and Scale - Animacje Rotate to animacje, w których element obraca się wokół własnej osi, podczas gdy w animacjach Scale animowany element zmniejsza lub zwiększa swój rozmiar. Przykład animacji, w której po najechaniu kursorem przycisk zwiększa swój rozmiar, a po kliknięciu obraca się wokół własnej osi:
Te animacje można uznać za podstawowe. Jednak nic nie stoi na przeszkodzie, aby łączyć te animacje i tworzyć bardziej zaawansowane i złożone efekty, które przyciągną uwagę i zainteresowanie użytkownika.
Aby stworzyć wysokiej jakości złożone animacje, najczęściej będziemy potrzebować specjalnych, dedykowanych bibliotek, które znacznie uproszczą i przyspieszą ten proces. Jedną z takich bibliotek w środowisku React.js jest Framer Motion.
Framer Motion to biblioteka open-source, która umożliwia łatwe i szybkie tworzenie animacji w środowisku React. Wykorzystując te same koncepcje co React, umożliwia m.in. animowanie elementów, które są usuwane z drzewa DOM, zarządzanie stanem komponentów i ich stanem animacji za pomocą specjalnie przygotowanych hooków, tworzenie niestandardowych hooków oraz zmniejszanie rozmiaru pakietu poprzez asynchroniczne ładowanie animacji.
Główne i najczęściej używane komponenty w bibliotece Framer Motion to komponenty motion. Jak możemy przeczytać w dokumentacji, “Komponenty Motion to prymitywy DOM zoptymalizowane pod kątem animacji 60fps i gestów.” Krótko mówiąc, komponenty motion są równoważne zwykłym elementom HTML, takim jak div, p, h1, button, wzbogaconym o specjalne propsy umożliwiające łatwą animację.
Najczęściej używane propsy to initial, który pozwala nam ustawić właściwości, od których powinna rozpocząć się animacja, animate - w którym określamy właściwości, do których nasz animowany element powinien dążyć podczas animacji, oraz exit, określający, co powinno się stać z animowanym elementem, gdy zostanie usunięty z drzewa DOM.
Załóżmy, że chcemy mieć niebieski kwadrat, który zmienia kolor na zielony, zwiększa rozmiar i obraca się o 360 stopni podczas animacji. Aby osiągnąć ten efekt za pomocą Framer Motion, potrzebujemy tylko kilku dodatkowych linii kodu.
Jak widać, to prosta sprawa! Ustawiamy wartości początkowe i te, do których nasz element ma animować i to wszystko!
Jak widać w powyższym przykładzie, użyliśmy właściwości zwanej transition. Dzięki niej możemy łatwo określić, między innymi, rodzaj animacji, czas, opóźnienie itp.
Istnieje kilka typów animacji dostępnych. W naszym przykładzie użyliśmy animacji spring, co nadało animacji bardziej realistyczny wygląd. Animacje można również konfigurować na wiele sposobów. Mamy możliwość zmiany właściwości takich jak masa, odbicie, tłumienie, sztywność czy prędkość. Na przykład, zmiana właściwości masy na wyższą wartość spowoduje, że obiekt będzie emitował większą masę, a ruch będzie znacznie bardziej ociężały. Dostępne właściwości animacji spring można sprawdzić tutaj.
Powyższa animacja rozpocznie się natychmiast po wyrenderowaniu elementu, tzn. po odświeżeniu strony. Co w sytuacjach, gdy chcemy, aby nasz element animował w odpowiedzi na przewijanie, tzn. tylko wtedy, gdy pojawi się w naszym widoku? Wszystko, co musimy zrobić, to zmienić właściwość animate na whileInView.
Jak widać, zmieniliśmy właściwość animate na whileInView. Nasz kwadrat zaczyna animować tylko wtedy, gdy pojawia się w widoku. Dodaliśmy również atrybut viewport once = true, aby nasz kwadrat nie animował się ponownie, gdy został przewinięty poza widok i ponownie się w nim pojawił. Możesz również zobaczyć, jak kwadrat zachowuje się, gdy zwiększamy jego właściwość masy.
Te przykłady to tylko proste animacje pojedynczych elementów. Co jeśli chcemy, aby animacje dotyczyły większej liczby komponentów? Czy musimy zastosować animowany obiekt do każdego elementu, który chcemy animować? A co jeśli chcemy, aby nasze elementy animowały z określonym opóźnieniem od ostatniego animowanego elementu? Czy musimy za każdym razem obejść właściwość opóźnienia? Aby odpowiedzieć na to pytanie, przyjrzyjmy się właściwości variants. Wariants pozwalają nam zdefiniować animacje, które propagują się w całym drzewie DOM. Przyjrzyjmy się następującemu przykładzie.
Jak widać w powyższym przykładzie, nie ustawiamy właściwości animate jako pojedynczego obiektu, lecz zamiast tego używamy właściwości variants.
Definiujemy warianty offScreen i onScreen i animujemy naszą listę, zmieniając przezroczystość. Następnie wykorzystujemy fakt, że te warianty propagują się w dół drzewa DOM i określamy, co powinno się stać z każdym poszczególnym elementem listy - komponentami Square. Dodatkowo, korzystając z wariantów, mamy możliwość zarządzania dziećmi animowanego elementu, na przykład, używając właściwości staggerChildren. Spowoduje to, że każdy kolejny element w naszej liście będzie się pojawiał z określonym opóźnieniem w stosunku do poprzedniego. Możesz przeczytać więcej o wariantach tutaj.
Powyższe przykłady pokazują tylko podstawową funkcjonalność, którą otrzymujemy, korzystając z Framer Motion. Zachęcam do zapoznania się z dokumentacją i sprawdzenia, co jeszcze ma do zaoferowania ta biblioteka.
Wspomniałem wcześniej, że Framer Motion pozwala nam animować elementy, które są usuwane z drzewa DOM. To prawda, ale omówimy to w następnym rozdziale.
Animowanie elementów podczas ich usuwania jest bardzo proste. Wszystko, co musimy zrobić, to owinąć nasz animowany komponent w specjalny wrapper zwany AnimatePresence. Wrapper pozwala nam opóźnić operację odmontowywania, aż animacja się zakończy, ale jeśli chcemy, aby nasz komponent był animowany, musimy pamiętać o zdefiniowaniu animacji exit.
Aby pokazać, jak możemy użyć AnimatePresence, stworzymy prostą aplikację przy użyciu frameworka Next.js. Aplikacja będzie miała dwie strony, a przejścia między nimi będą animowane. Zatem stwórzmy kilka Page Transitions.
Zacznijmy od wygenerowania projektu i zainstalowania niezbędnych bibliotek. Instrukcje dotyczące tworzenia nowego projektu przy użyciu Next.js można znaleźć tutaj. Będziemy również używać TypeScript w projekcie, więc zalecam wygenerowanie projektu z flagą --typescript.
Ok, mamy projekt, teraz zainstalujmy niezbędne biblioteki. Oprócz biblioteki Framer Motion, użyjemy również Tailwind CSS, co pozwoli nam szybko stylizować bez konieczności tworzenia plików CSS. Aby zainstalować bibliotekę Framer Motion, wystarczy wkleić npm i framer-motion w konsoli i ją zainstalować. Instalacja Tailwind jest nieco bardziej skomplikowana, a pełne instrukcje można znaleźć tutaj. Nas interesują kroki 2-4.
Najpierw edytujmy nasz plik pages/index.tsx. Wyświetlimy prosty nagłówek i trzy karty, które będą linkami do naszej następnej strony. Każdy z komponentów będzie miał zdefiniowane animacje przy użyciu wariantów. Aby kod był łatwiejszy do odczytania w przypadku wpisu na blogu, umieszczę wszystko w jednym pliku. Plik index.tsx wygląda tak:
Wspomniane karty są linkami do naszej drugiej strony, którą teraz stworzymy. W folderze pages dodaj plik [id].tsx. Na tej stronie będziemy mieli krótki tekst wraz z linkiem powracającym do strony głównej. Cały plik wygląda tak:
Jeśli teraz uruchomimy projekt, niestety zauważymy, że nasze animacje nie działają. Jest to spowodowane tym, że stworzyliśmy warianty onEnter i initial i przypisaliśmy je do naszych elementów, ale nigdzie nie zdefiniowaliśmy, do jakich konkretnych właściwości nasze warianty się odnoszą, jak w przykładzie SquareList powyżej. Zrobimy to teraz w osobnym komponencie.
Stwórzmy komponent Layout. Renderujemy w nim wspomniane AnimatePresence.
Nasz nowy komponent będzie wrapperem dla całej aplikacji. Jest tutaj element div, który będzie animował nasze przejście z jednej strony na drugą. Definiujemy tutaj wcześniej wspomniane warianty i przypisujemy je do odpowiednich właściwości. Teraz wiemy, że warianty mają zdolność propagacji głęboko w drzewie DOM, więc wszystkie elementy mają dostęp do zmian w wariantach, dopóki nie zdefiniują swoich własnych właściwości, takich jak animate.
Podczas animacji onExit, oprócz zmiany przezroczystości, użyjemy właściwości clipPath, aby stworzyć animację wycinania naszej strony z lewej do prawej. Musimy również pamiętać, że aby element był poprawnie animowany przed jego odmontowaniem, musimy nadać mu unikalną właściwość key, która pozwoli AnimatePresence śledzić obecność elementu w drzewie DOM. Nowo utworzony komponent jest renderowany w pliku _app.tsx.
Jeśli teraz uruchomimy nasz projekt, powinniśmy zobaczyć następujący efekt:
Jak widać, udało nam się stworzyć prostą animację przejścia między stronami. Dodatkowo każdy z naszych elementów ma animację Fade in i Slide in. Gorąco polecam eksperymentowanie z dostępnym kodem i sprawdzenie, jak reaguje na zmiany.
Jak widać, Framer Motion to bardzo łatwa w użyciu biblioteka do tworzenia animacji w React. Oferuje wiele komponentów i funkcjonalności, które znacznie przyspieszają proces tworzenia animacji. Większość z nich nie została ponownie omówiona, ale zachęcam do zapoznania się z nimi. Warto również wspomnieć o dobrze napisanej dokumentacji, która znacznie ułatwia pracę.
Czy warto rozważyć Framer Motion jako bibliotekę do animacji? Zdecydowanie! Jednak przed podjęciem ostatecznej decyzji musimy pamiętać, że mimo iż Framer Motion jest świetną biblioteką, ma wiele konkurencji do rozważenia, takich jak Gsap, React-spring i inne.
11 marca 2025 • Maria Pradiuszyk