Pierwsze kroki z animacjami przewijanymi w CSS

1. Zanim zaczniesz

Animacje przewijane pozwalają kontrolować odtwarzanie animacji na podstawie pozycji przewijania kontenera przewijania. Oznacza to, że podczas przewijania w górę lub w dół animacja przesuwa się do przodu lub do tyłu. Dodatkowo w przypadku animacji przewijanych możesz sterować animacją na podstawie pozycji elementu w jego kontenerze przewijania. Pozwala to tworzyć interesujące efekty, takie jak obraz tła z paralaksą, paski postępu przewijania i obrazy, które odsłaniają się, gdy się pojawią.

Nowością w Chrome 115 jest obsługa zestawu klas JavaScriptu i właściwości CSS, które umożliwiają łatwe tworzenie deklaratywnych animacji przewijanych. Te nowe interfejsy API działają w połączeniu z dotychczasowymi interfejsami Web Animations i CSS Animations.

Dzięki temu ćwiczeniu w Codelabs dowiesz się, jak za pomocą CSS tworzyć animacje oparte na przewijaniu. Po ukończeniu tego ćwiczenia w programie poznasz wiele nowych właściwości CSS wprowadzonych w tej ciekawej funkcji, takich jak scroll-timeline, view-timeline, animation-timeline i animation-range.

Czego się nauczysz

  • Jak utworzyć efekt paralaksy w tle za pomocą osi czasu przewijania w CSS.
  • Jak utworzyć pasek postępu za pomocą osi czasu przewijania w CSS.
  • Jak utworzyć efekt odkrywania obrazu za pomocą widoku osi czasu w CSS.
  • Jak kierować reklamy na różne typy zakresów na osi czasu wyświetlania w CSS.

Czego potrzebujesz

Jedna z tych kombinacji urządzeń:

  • najnowszą wersję Chrome (115 lub nowszą) w systemie ChromeOS, macOS lub Windows z „eksperymentalnymi funkcjami platformy internetowej”. flaga ustawiona na „Enabled” (Włączono).
  • Podstawowa znajomość języka HTML
  • Podstawowa wiedza o kodzie CSS, w szczególności w zakresie animacji

2. Konfiguracja

Wszystko, czego potrzebujesz w tym projekcie, jest dostępne w repozytorium GitHub. Na początek skopiuj kod i otwórz go w swoim ulubionym środowisku programistycznym.

  1. Otwórz nową kartę przeglądarki i wejdź na stronę https://github.com/googlechromelabs/io23-scroll-driven-animations-codelab.
  2. Skopiuj repozytorium.
  3. Otwórz kod w preferowanym IDE.
  4. Uruchom npm install, aby zainstalować zależności.
  5. Uruchom npm start i wejdź na stronę http://localhost:3000/.
  6. Jeśli usługa npm nie jest zainstalowana, możesz też otworzyć plik src/index.html w Chrome.

3. Więcej informacji o osiach czasu animacji

Domyślnie animacja dołączana do elementu jest wyświetlana na osi czasu dokumentu. Oznacza to, że po załadowaniu strony animacja przesuwa się do przodu w miarę upływu czasu. To jest domyślna oś czasu animacji, a do tej pory była to jedyna oś czasu animacji, do której masz dostęp.

Animacje przewijane oferują dostęp do 2 nowych typów osi czasu:

  • Oś czasu przewijania
  • Wyświetl oś czasu postępów

W CSS te osie czasu można dołączyć do animacji za pomocą właściwości animation-timeline. Zobacz, co oznaczają nowe oś czasu i czym różnią się od siebie.

Oś czasu przewijania

Oś czasu przewijania to oś czasu animacji powiązana z postępem w pozycji przewijania kontenera przewijania – nazywanego też obszarem przewijania lub przewijaną – wzdłuż konkretnej osi. Konwertuje pozycję w zakresie przewijania na procent postępu na osi czasu.

Początkowa pozycja przewijania reprezentuje 0% postępu, a końcowa pozycja przewijania – cały postęp. Na tej wizualizacji widać, że postęp jest zliczany od 0% do 100% podczas przewijania w dół.

Wyświetl oś czasu postępów

Ten typ osi czasu jest powiązany ze względnym postępem określonego elementu w kontenerze przewijania. Tak jak w przypadku osi czasu postępu przewijania, śledzenie przesunięcia przewijania jest liczone. W przeciwieństwie do osi czasu postępu przewijania o postępy decyduje względna pozycja obiektu w tym przewijaniu. Jest to porównywalne ze stanem IntersectionObserver, który śledzi, jak bardzo element jest widoczny w obszarze przewijania. Jeśli element nie jest widoczny w komponencie do przewijania, oznacza to, że nie ma części wspólnej. Jeśli jest widoczny wewnątrz elementu przewijania, nawet w przypadku jego najmniejszej części, oznacza, że element krzyżuje się.

Oś czasu wyświetlania rozpoczyna się w momencie, gdy obiekt zaczyna krzyżować się z elementem przewijania, a kończy się, gdy obiekt przestanie przecinać obszar przewijania. Na tej wizualizacji zauważ, że postęp zaczyna zliczać od 0%, gdy obiekt znajdzie się w kontenerze przewijania, i osiągnąć 100% w momencie opuszczenia kontenera przewijania.

Domyślnie animacja połączona z osią czasu wyświetlania jest dołączana do całego jej zakresu. Zaczyna się od momentu, gdy obiekt znajdzie się w obszarze przewijania, a kończy w momencie, gdy go opuści.

Możesz też powiązać go z konkretną częścią osi czasu wyświetlania postępu, określając zakres, do którego powinna zostać przypisana. Może to być na przykład tylko wtedy, gdy temat jest otwierany w obszarze przewijania. W poniższej wizualizacji postęp zaczyna się liczyć od 0%, gdy obiekt znajdzie się w kontenerze przewijania, ale osiągnie 100% stopnia od momentu całkowitego przecięcia się z obiektem.

Możliwe zakresy widoku osi czasu, na które możesz kierować reklamy, to cover, contain, entry, exit, entry-crossing i exit-crossing. Zakresy zostały objaśnione w dalszej części tego ćwiczenia w Codelabs, ale jeśli nie możesz się doczekać, skorzystaj z narzędzia dostępnego na stronie https://goo.gle/view-timeline-range-tool.

4. Tworzenie efektu w tle z efektem paralaksy

Pierwszym efektem, który możesz dodać do strony, jest efekt paralaksy w głównym obrazie tła. Podczas przewijania strony w dół obraz tła powinien się przesuwać, ale z różną prędkością. W tym celu polegasz na osi czasu postępu przewijania.

Aby wdrożyć to ustawienie, musisz wykonać 2 czynności:

  1. Utwórz animację, która zmienia pozycję obrazu tła.
  2. Połącz animację z postępem przewijania dokumentu.

Tworzenie animacji

  1. Aby utworzyć animację, użyj zwykłego zestawu klatek kluczowych. Zmień w niej położenie tła z 0% w pionie na 100%:

src/styles.css

@keyframes move-background {
  from {
    background-position: 50% 0%;
  }
  to {
    background-position: 50% 100%;
  }
}
  1. Teraz dołącz te klatki kluczowe do elementu Body:

src/styles.css

body {
  animation: 1s linear move-background;
}

Po użyciu tego kodu animacja move-background jest dodawana do elementu Body. Właściwość animation-duration jest ustawiona na 1 sekundę i używa wygładzania linear.

Najłatwiejszym sposobem utworzenia osi czasu przewijania jest użycie funkcji scroll(). Spowoduje to utworzenie anonimowej osi czasu przewijania, którą możesz ustawić jako wartość właściwości animation-timeline.

Funkcja scroll() akceptuje argumenty <scroller> i <axis>.

Akceptowane wartości dla argumentu <scroller>:

  • nearest Wykorzystuje kontener przewijania do najbliższego elementu nadrzędnego (domyślnie).
  • root Używa widocznego obszaru dokumentu jako kontenera przewijania.
  • self Używa samego elementu jako kontenera przewijania.

Akceptowane wartości dla argumentu <axis>:

  • block Wykorzystuje pomiar postępu wzdłuż osi bloku kontenera przewijania (domyślnie).
  • inline Używa pomiaru postępu wzdłuż wbudowanej osi kontenera przewijania.
  • y Korzysta z miary postępu wzdłuż osi Y kontenera przewijania.
  • x Określa postęp na osi X kontenera przewijania.

Aby połączyć animację z głównym elementem przewijania na osi bloku, do elementu scroll() należy przekazywać wartości root i block. Łączna wartość to scroll(root block).

  • Ustaw scroll(root block) jako wartość właściwości animation-timeline treści.
  • Poza tym funkcja animation-duration wyrażona w sekundach nie ma sensu, dlatego ustaw czas trwania na auto. Jeśli nie określisz wartości animation-duration, zostanie użyta domyślna wartość auto.

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll(root block);
}

Główny element przewijający jest również najbliższym nadrzędnym elementem przewijającym elementu body, więc możesz też użyć wartości nearest:

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll(nearest block);
}

nearest i block to wartości domyślne, więc możesz je nawet pominąć. W takim przypadku kod można uprościć do następującego:

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll();
}

Weryfikowanie zmian

Jeśli wszystko przebiegło pomyślnie, kod powinien wyglądać tak:

Jeśli nie, sprawdź gałąź solution-step-1 kodu.

5. Utwórz pasek postępu dla galerii obrazów

Na stronie znajduje się pozioma karuzela. Pasek postępu powinien wskazywać, które zdjęcie aktualnie oglądasz.

Znaczniki karuzeli wyglądają tak:

src/index.html

<div class="gallery">
  <div class="gallery__scrollcontainer" style="--num-images: 3;">
    <div class="gallery__progress"></div>
    <div class="gallery__entry">
      ...
    </div>
    <div class="gallery__entry">
      ...
    </div>
    <div class="gallery__entry">
      ...
    </div>
  </div>
</div>

Klatki kluczowe na pasku postępu są już na swoim miejscu i wyglądają tak:

src/styles.css

@keyframes adjust-progress {
  from {
    transform: scaleX(calc(1 / var(--num-images)));
  }
  to {
    transform: scaleX(1);
  }
}

Tę animację należy dołączyć do pliku .Element gallery__progress z osią postępu przewijania. Jak pokazano w poprzednim kroku, możesz to osiągnąć, tworząc anonimową oś czasu przewijania za pomocą funkcji scroll():

src/styles.css

.gallery__progress {
  animation: linear adjust-progress;
  animation-duration: auto;
  animation-timeline: scroll(nearest inline);
}

Chociaż fragment kodu może się wydawać, że zadziała, nie jest to spowodowane tym, jak działają automatyczne wyszukiwanie kontenerów przewijania za pomocą funkcji nearest. Podczas wyszukiwania najbliższego elementu przewijania element bierze pod uwagę tylko te elementy, które mogą mieć wpływ na jego pozycję. Element .gallery__progress ma pozycję bezwzględną, więc pierwszym elementem nadrzędnym, który określa jego pozycję, jest element .gallery, ponieważ ma on zastosowany element position: relative. Oznacza to, że element .gallery__scrollcontainer – czyli element przewijający, na który należy ustawić kierowanie – nie jest w ogóle brany pod uwagę podczas tego automatycznego wyszukiwania.

Aby obejść ten problem, utwórz w elemencie .gallery__scrollcontainer nazwaną oś czasu przewijania i połącz z nią element .gallery__progress, używając tej nazwy.

Aby utworzyć w elemencie nazwaną oś czasu przewijania, ustaw odpowiednią wartość właściwości CSS scroll-timeline-name w kontenerze przewijania. Wartość musi zaczynać się od --.

Galeria przewija się w poziomie, więc musisz też ustawić właściwość scroll-timeline-axis. Dozwolone wartości są takie same jak argument <axis> funkcji scroll().

Na koniec, aby połączyć animację z osią czasu przewijania, ustaw właściwość animation-timeline elementu, który ma być animowany, na tę samą wartość co identyfikator używany w przypadku elementu scroll-timeline-name.

  • Zmień plik styles.css, dodając do niego te dane:

src/styles.css

.gallery__scrollcontainer {
  /* Create the gallery-is-scrolling timeline */
  scroll-timeline-name: --gallery-is-scrolling;
  scroll-timeline-axis: inline;
}

.gallery__progress {
  animation: linear adjust-progress;
  animation-duration: auto;
  /* Set gallery-is-scrolling as the timeline */
  animation-timeline: --gallery-is-scrolling;
}

Weryfikowanie zmian

Jeśli wszystko przebiegło pomyślnie, kod powinien wyglądać tak:

Jeśli nie, sprawdź gałąź solution-step-2 kodu.

6. Animuj obrazy w galerii, gdy otwierają i znikają z obszaru przewijania

Skonfiguruj anonimową oś czasu wyświetlania postępów

Miłym efektem jest zanikanie obrazów w galerii, gdy pojawią się w widoku. W tym celu możesz skorzystać z osi czasu wyświetlania postępów.

Aby utworzyć oś czasu wyświetlania postępu, możesz użyć funkcji view(). Jej akceptowane argumenty to <axis> i <view-timeline-inset>.

  • Wartość <axis> jest taka sama jak oś czasu postępu przewijania i określa, którą oś śledzić.
  • <view-timeline-inset> pozwala określić przesunięcie (dodatnie lub ujemne), co pozwala dostosować granice w przypadku, gdy element jest uznawany za widoczny lub nie.
  • Klatki kluczowe są już na swoim miejscu, więc musisz je tylko dołączyć. Aby to zrobić, utwórz oś czasu wyświetlania postępów dla każdego elementu .gallery__entry.

src/styles.css

@keyframes animate-in {
  from {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
  to {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
}

.gallery__entry {
  animation: linear animate-in;
  animation-duration: auto;
  animation-timeline: view(inline);
}

Ogranicz zakres osi czasu postępu wyświetlania

Jeśli zapiszesz kod CSS i wczytasz stronę, elementy wyłaniają się, ale coś nie będzie wyglądało. Zaczynają się od przezroczystości 0, gdy są całkowicie niewidoczne, a kończą jako nieprzezroczystość 1 po zamknięciu.

Wynika to z faktu, że domyślny zakres osi czasu procesu wyświetlania to pełny zakres. Jest to tzw. zakres cover.

  1. Jeśli chcesz kierować reklamy tylko na zakres entry tematu, użyj właściwości CSS animation-range, by ograniczyć czas trwania animacji.

src/styles.css

.gallery__entry {
  animation: linear fade-in;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry 0% entry 100%;
}

Animacja zaczyna się od entry 0% (temat jest za chwilę przesuwany w stronę paska przewijania) do entry 100% (obiekt w pełni przeszedł do obszaru przewijania).

Możliwe zakresy widoku osi czasu:

  • cover Reprezentuje pełny zakres osi czasu postępu wyświetlania.
  • entry Reprezentuje zakres, w którym pole podmiotu zabezpieczeń wchodzi w zakres widoczności postępu wyświetlania.
  • exit Reprezentuje zakres, w którym pole podmiotu zabezpieczeń wychodzi z zakresu widoczności postępu wyświetlania.
  • entry-crossing Reprezentuje zakres, w którym pole podmiotu zabezpieczeń przekracza końcową krawędź.
  • exit-crossing Reprezentuje zakres, w którym pole podmiotu zabezpieczeń przekracza początkową krawędź.
  • contain Reprezentuje zakres, w którym pole podmiotu zabezpieczeń jest w pełni zawarte lub pokrywa zakres widoczności postępu wyświetlania w obszarze przewijania. Zależy to od tego, czy obiekt jest wyższy czy krótszy od przewijania.

Skorzystaj z narzędzia dostępnego na stronie https://goo.gle/view-timeline-range-tool, aby zobaczyć, co oznacza każdy z zakresów i jak wartości procentowe wpływają na pozycję początkową i końcową.

  1. Zakresy początkowy i końcowy są tutaj takie same oraz użyte domyślne przesunięcia, więc uprość pole animation-range, tworząc jedną nazwę zakresu animacji:

src/styles.css

.gallery__entry {
  animation: linear animate-in;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry;
}
  • Aby zanikać obrazy po wyjściu z paska przewijania, możesz zrobić to samo co w animacji, ale ustawić inny zakres.

src/styles.css

@keyframes animate-out {
  from {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
  to {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
}

.gallery__entry {
  animation: linear animate-in, linear animate-out;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry, exit;
}

Klatki kluczowe animate-in zostaną zastosowane do zakresu entry, a klatki kluczowe animate-out do zakresu exit.

Weryfikowanie zmian

Jeśli wszystko przebiegło pomyślnie, kod powinien wyglądać tak:

Jeśli nie, sprawdź gałąź solution-step-3 kodu.

7. Używaj jednego zestawu klatek kluczowych, aby animować obrazy z galerii w momencie, gdy otwierają i znikają w obszarze przewijania.

Przypadek jednego zestawu klatek kluczowych

Zamiast dołączać dwie animacje do różnych zakresów, możesz utworzyć jeden zestaw klatek kluczowych, który zawiera już informacje o zakresie.

Kształt klatek kluczowych wygląda tak:

@keyframes keyframes-name {
  range-name range-offset {
    ...
  }
  range-name range-offset {
    ...
  }
}
  1. Łącz klatki kluczowe rozjaśniania i zanikania w ten sposób:

src/styles.css

@keyframes animate-in-and-out {
  entry 0% {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
  entry 90% {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }

  exit 10% {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
  exit 100% {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
}
  1. Gdy w klatkach kluczowych znajdują się informacje o zakresie, nie musisz już osobno określać elementu animation-range. Dołącz klatki kluczowe jako właściwość animation.

src/styles.css

.gallery__entry {
  animation: linear animate-in-and-out both;
  animation-duration: auto;
  animation-timeline: view(inline);
}

Weryfikowanie zmian

Jeśli wszystko poszło dobrze, wynik powinien być taki sam jak w poprzednim kroku. Jeśli nie, sprawdź gałąź solution-step-4 kodu.

8. Gratulacje!

To już ćwiczenia z programowania i teraz wiesz, jak tworzyć osie czasu postępu przewijania i wyświetlać oś czasu postępów w CSS.

Więcej informacji

Zasoby: