Leniwe ładowanie filmu

Podobnie jak w przypadku elementów graficznych, film możesz też leniwie ładować. Filmy są zwykle ładowane za pomocą elementu <video> (chociaż inna metoda wykorzystująca metodę <img> jest dostępna w ograniczonym zakresie). Sposób leniwego ładowania <video> zależy jednak od konkretnego przypadku użycia. Omówmy kilka scenariuszy, które wymagają innego rozwiązania.

Filmy, które nie odtwarzają się automatycznie

W przypadku filmów, w których odtwarzanie jest inicjowane przez użytkownika (czyli takich, które nie są odtwarzane automatycznie), wskazane 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 atrybut preload o wartości none uniemożliwia przeglądarkom wstępne wczytywanie jakich danych wideo. Atrybut poster udostępnia elementowi <video> obiekt zastępczy, który zajmie całą przestrzeń podczas wczytywania filmu. Dzieje się tak, ponieważ domyślne zachowanie wczytywania filmu może się różnić w zależności od przeglądarki:

  • W Chrome domyślną wartością parametru preload było auto, a od Chrome 64 wartość domyślna to metadata. Jednak w komputerowej wersji Chrome część filmu może być wstępnie wczytywana za pomocą nagłówka Content-Range. Inne przeglądarki oparte na Chromium i Firefox działają podobnie.
  • Podobnie jak w Chrome na komputerze, przeglądarka Safari w wersji 11.0 na komputery wstępnie wczytuje zakres filmów. Od wersji 11.2 wstępnie wczytywane są tylko metadane filmu. W Safari w systemie iOS filmy nigdy nie są wstępnie wczytywane.
  • Gdy włączony jest tryb oszczędzania danych, preload domyślnie przyjmuje wartość none.

Domyślne zachowania przeglądarki w odniesieniu do strony preload nie są ustalone bezwzględnie, dlatego najprawdopodobniej najlepiej będzie wyrażać zgodę na wulgaryzmy. W takich przypadkach, gdy użytkownik inicjuje odtwarzanie, najprostszym sposobem na odroczenie wczytywania filmu na wszystkich platformach jest użycie właściwości preload="none". Atrybut preload nie jest jedynym sposobem na opóźnienie wczytywania treści wideo. Szybkie odtwarzanie ze wstępnym wczytywaniem filmów może podsunąć Ci pomysły i wgląd na temat pracy z odtwarzaniem filmów w języku JavaScript.

Niestety ta funkcja nie jest przydatna, gdy chcesz użyć filmu zamiast animowanych GIF-ów. Opisaliśmy je w następnej kolejności.

Film pełniący funkcję animowanego zamiennika GIF-a

Animowane GIF-y mają szerokie zastosowanie, ale pod wieloma względami nie są od nich odpowiedniki, zwłaszcza pod względem rozmiaru plików. Animowane pliki GIF mogą trwać do kilku megabajtów danych. Filmy o podobnej jakości wizualnej są zwykle znacznie mniejsze.

Użycie elementu <video> jako zamiennika animowanego GIF-a nie jest tak proste jak element <img>. Animowane pliki GIF mają trzy cechy:

  1. Po wczytaniu są odtwarzane automatycznie.
  2. Są one odtwarzane w pętli (chociaż nie zawsze tak jest).
  3. Nie mają ścieżki audio.

Jeśli chcesz to osiągnąć za pomocą elementu <video>, wygląda to 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 są jasne. Parametr playsinline jest niezbędny do autoodtwarzania na iOS. Teraz możesz skorzystać z dostępnego zamiennika filmu jako GIF-a, który działa na różnych platformach. Ale jak go leniwie wczytywać? 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>

Dodaliśmy też atrybut poster, który umożliwia wstawianie zmiennej zajmującej miejsce w elemencie <video> do czasu leniwego ładowania filmu. Tak jak w przypadku przykładów leniwego ładowania <img>, umieść adres URL filmu w atrybucie data-src w każdym elemencie <source>. Następnie użyj kodu JavaScript podobnego do przykładów leniwego ładowania obrazów opartych na obserwacji Intersection:

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);
    });
  }
});

Gdy używasz leniwego ładowania elementu <video>, musisz powtórzyć wszystkie elementy podrzędne <source> i zmienić ich atrybuty data-src na atrybuty src. Gdy to zrobisz, musisz wywołać ładowanie filmu, wywołując metodę load elementu, co spowoduje automatyczne rozpoczęcie odtwarzania multimediów zgodnie z atrybutem autoplay.

Korzystając z tej metody, otrzymujesz rozwiązanie wideo, które emuluje animowane zachowania GIF-ów, ale nie wymaga angażowania danych w taki sam sposób jak animowane GIF-y. Treści można też ładować leniwie.

Leniwe ładowanie bibliotek

W przypadku leniwego ładowania filmów mogą Ci pomóc te biblioteki:

  • vanilla-lazyload i lozad.js to bardzo lekkie opcje, które korzystają tylko z intersection Observer. Z tego względu są one bardzo wydajne, ale przed użyciem w starszych przeglądarkach trzeba je wypełnić.
  • yall.js to biblioteka, która korzysta z obserwacji intersekcji i korzysta z modułów obsługi zdarzeń. Może też leniwie wczytywać obrazy filmu poster za pomocą atrybutu data-poster.
  • Jeśli potrzebujesz biblioteki leniwego ładowania specyficznej dla React, możesz użyć funkcji react-lazyload. Nie korzysta on z intersection Observer, ale zapewnia znaną metodę leniwego wczytywania obrazów dla osób przyzwyczajonych do tworzenia aplikacji w React.

Każda z tych bibliotek leniwego ładowania jest dobrze udokumentowana i zawiera wiele wzorców znaczników przydatnych w różnych zadaniach związanych z leniwym ładowaniem.