Leniwe ładowanie filmu

Podobnie jak w przypadku elementów graficznych, leniwe ładowanie wideo. Filmy są zwykle wczytywane za pomocą elementu <video> (chociaż opracowano alternatywną metodę wykorzystującą <img>, która ma ograniczoną implementację). Sposób leniwego ładowania <video> zależy jednak od konkretnego przypadku użycia. Omówmy kilka scenariuszy, których każdy wymaga innego rozwiązania.

Filmy, które nie są odtwarzane automatycznie

W przypadku filmów, których odtwarzanie jest inicjowane przez użytkownika (czyli takich, które nie są odtwarzane automatycznie), zalecane może być określenie atrybutu preload w elemencie <video>:

<video controls preload="none" poster="one-does-not-simply-placeholder.jpg">
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

W powyższym przykładzie użyto atrybutu preload o wartości none, aby uniemożliwić przeglądarkom wstępne wczytywanie jakichkolwiek danych wideo. Atrybut poster nadaje elementowi <video> obiekt zastępczy, który będzie zajmować miejsce podczas wczytywania filmu. Powodem jest to, że domyślne zachowanie wczytywania filmu może się różnić w zależności od przeglądarki:

  • W Chrome domyślnym ustawieniem dla preload było auto, ale od wersji Chrome 64 jest to teraz metadata. Mimo to w komputerowej wersji Chrome część filmu może być wstępnie wczytana za pomocą nagłówka Content-Range. Inne przeglądarki oparte na Chromium oraz Firefox działają podobnie.
  • Tak jak w przypadku Chrome na komputerze, przeglądarka Safari 11.0 na komputery będzie wstępnie wczytywała wcześniej szereg filmów. Od wersji 11.2 wstępnie wczytywane są tylko metadane filmu. W Safari na iOS filmy nigdy nie są wstępnie wczytywane.
  • Gdy włączony jest tryb oszczędzania danych, preload ma domyślnie wartość none.

Domyślne zachowania przeglądarki w odniesieniu do strony preload nie są bardzo proste, więc najlepiej nie przesadzić z ilością wulgaryzmów. W przypadkach, gdy użytkownik inicjuje odtwarzanie filmu, najprostszym sposobem na odroczenie wczytywania filmu na wszystkich platformach jest użycie parametru preload="none". Atrybut preload nie jest jedynym sposobem na odroczenie wczytywania treści wideo. Szybkie odtwarzanie z wstępnym wczytywaniem filmów może podsunąć Ci pomysły i wskazówki dotyczące pracy z odtwarzaniem filmów w języku JavaScript.

Niestety nie sprawdza się on w przypadku zastępowania animowanych GIF-ów, które opisujemy poniżej.

Do filmów zastępujących animowany GIF

Animowane pliki GIF są powszechnie wykorzystywane, ale pod wieloma względami nie różnią się od odpowiedników wideo, zwłaszcza pod względem rozmiaru. Animowane pliki GIF mogą zajmować pomiar nawet kilku megabajtów danych. Filmy o podobnej jakości wizualnej są znacznie mniejsze.

Zastosowanie elementu <video> jako zamiennika animowanego GIF-a nie jest tak proste jak element <img>. Animowane GIF-y mają 3 cechy:

  1. Po wczytaniu odtwarzają się automatycznie.
  2. Zapętlają się w sposób ciągły (chociaż nie zawsze tak jest).
  3. Nie mają ścieżki audio.

Osiągnięcie tego za pomocą elementu <video> wygląda mniej więcej tak:

<video autoplay muted loop playsinline>
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

Atrybuty autoplay, muted i loop nie wymagają wyjaśnień. Aby korzystać z autoodtwarzania w iOS, musisz wybrać playsinline. Możesz skorzystać z funkcji zastąpienia wideo jako GIF-a, która działa na różnych platformach. Ale jak uniknąć leniwego ładowania? Aby rozpocząć, odpowiednio zmodyfikuj znaczniki <video>:

<video class="lazy" autoplay muted loop playsinline width="610" height="254" poster="one-does-not-simply.jpg">
  <source data-src="one-does-not-simply.webm" type="video/webm">
  <source data-src="one-does-not-simply.mp4" type="video/mp4">
</video>

Zwróć uwagę na dodanie atrybutu poster. Umożliwia on określenie obiektu zastępczego, który będzie zajmować miejsce w elemencie <video> do momentu, aż film będzie się ładować leniwie. Tak jak w przypadku przykładów leniwego ładowania (<img>) umieść adres URL filmu w atrybucie data-src na każdym elemencie <source>. Następnie użyj kodu JavaScript podobnego do przykładów leniwego ładowania obrazów opartego na Intersection Observer:

document.addEventListener("DOMContentLoaded", function() {
  var lazyVideos = [].slice.call(document.querySelectorAll("video.lazy"));

  if ("IntersectionObserver" in window) {
    var lazyVideoObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(video) {
        if (video.isIntersecting) {
          for (var source in video.target.children) {
            var videoSource = video.target.children[source];
            if (typeof videoSource.tagName === "string" && videoSource.tagName === "SOURCE") {
              videoSource.src = videoSource.dataset.src;
            }
          }

          video.target.load();
          video.target.classList.remove("lazy");
          lazyVideoObserver.unobserve(video.target);
        }
      });
    });

    lazyVideos.forEach(function(lazyVideo) {
      lazyVideoObserver.observe(lazyVideo);
    });
  }
});

W przypadku leniwego ładowania elementu <video> musisz iterować wszystkie elementy podrzędne <source> i zmienić ich atrybuty data-src na atrybuty src. Gdy to zrobisz, musisz aktywować wczytywanie filmu, wywołując metodę load elementu. Po jej zakończeniu odtwarzanie multimediów rozpocznie się automatycznie zgodnie z atrybutem autoplay.

Dzięki tej metodzie otrzymujesz rozwiązanie wideo, które emuluje animowane działania GIF-ów, ale nie zużywa tak dużo danych jak w przypadku animowanych GIF-ów. Możesz je też leniwie ładować.

Biblioteki z leniwym ładowaniem

Te biblioteki ułatwiają leniwe ładowanie filmów:

  • vanilla-lazyload i lozad.js to bardzo lekkie opcje, które korzystają tylko z obszaru Intersection Observer. Są więc bardzo skuteczne, ale przed użyciem w starszych przeglądarkach muszą zostać wypełnione.
  • yall.js to biblioteka, która używa obserwatora interakcji i korzysta z modułów obsługi zdarzeń. Może też leniwie ładować obrazy poster filmów za pomocą atrybutu data-poster.
  • Jeśli potrzebujesz biblioteki leniwego ładowania w React, możesz użyć biblioteki react-leniwe ładowanie. Choć nie wykorzystuje on Intersection Observer, zapewnia znaną metodę leniwego ładowania obrazów dla osób przyzwyczajonych do tworzenia aplikacji za pomocą React.

Każda z tych bibliotek leniwego ładowania jest dobrze udokumentowana i zawiera mnóstwo wzorców znaczników przydatnych w różnych działaniach tego typu.