延迟加载视频

图片元素一样,您还可以延迟加载视频。视频通常使用 <video> 元素加载(尽管 替代方法 <img>已 出现,但实施有限)。如何延迟加载 <video> 取决于 应用场景。我们来讨论几种情况,其中每种场景都需要 解决方案

对于不会自动播放的视频

对于由用户发起的播放的视频(即没有 自动播放),指定 preload 属性 <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>

上面的示例使用值为 nonepreload 属性来阻止浏览器 任何视频数据。poster 属性为 <video> 元素提供一个占位符,以便在视频加载时占据空间。原因在于 视频加载的默认行为可能因浏览器而异:

  • 在 Chrome 中,preload 的默认设置之前是 auto,但自 Chrome 64 起, 默认为 metadata。尽管如此,在桌面版 Chrome 上 视频可以使用 Content-Range 标头预加载。其他基于 Chromium 的浏览器和 Firefox 的行为方式类似。
  • 与桌面版 Chrome 一样,Safari 11.0 桌面版会预加载一定范围 视频内容 从 11.2 版开始,系统仅会预加载视频元数据。在 iOS 设备上的 Safari 中, 预加载
  • 流量节省程序模式处于 已启用,preload 默认为 none

由于浏览器在 preload 方面的默认行为并非一成不变, 发布露骨内容可能是最好的选择。在这种情况下,如果用户发起 使用 preload="none" 是推迟视频加载的最简单方式, 所有平台。preload 属性不是延迟加载的唯一方式 视频内容快速播放视频 预加载可能会提供 一些使用 JavaScript 播放视频的想法和见解。

很抱歉,当你想用视频代替 动画 GIF,我们将在后面的课程中介绍相关内容。

用于替换动画 GIF

虽然动画 GIF 应用广泛,但就 尤其是在文件大小方面GIF 动画格式可以扩展到 几 MB 的数据范围视觉效果相当的视频往往 也要小得多

使用 <video> 元素代替动画 GIF 并不像 像 <img> 元素一样简单直接。动画 GIF 具有三个特征:

  1. 视频加载后会自动播放。
  2. 它们会不断循环(但有时 case)。
  3. 没有音轨。

使用 <video> 元素实现此目标的方式如下所示:

<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>

autoplaymutedloop 属性均一目了然,无需另作说明。 以下时间过后必须 playsinline 才能自动播放 iOS 版应用。现在,您有了 可跨平台使用“视频即 GIF”替换。但如何 该怎么办呢?首先,请相应地修改 <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>

您会看到新增了 poster 属性, 用于指定一个占位符来占用 <video> 元素的空间 直到视频被延迟加载与 <img> 延迟加载示例一样, 将视频网址存储在每个 <source>data-src 属性中 元素。然后,使用与 基于 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);
    });
  }
});

延迟加载 <video> 元素时,您需要遍历所有子元素, <source> 元素,并将其 data-src 属性转换为 src 属性。一次 您已完成其操作,则需要通过调用 元素的 load 方法,之后媒体将自动开始播放 根据 autoplay 属性计算得出。

通过这种方法,您可以获得模拟动画 GIF 行为的视频解决方案, 但不会像动画 GIF 那样消耗大量流量, 您可以延迟加载这些内容

延迟加载库

以下库可以帮助您延迟加载视频:

  • vanilla-lazyloadlozad.js 是超轻量级选项 仅使用 Intersection Observer。因此,它们虽然性能出色 需要先进行 polyfill 操作,然后才能在旧版浏览器上使用。
  • yall.js是一个使用 Intersection Observer,并回退到事件处理脚本。它还可以使用 data-poster 属性延迟加载视频 poster 图片。
  • 如果您需要 React 专用的延迟加载库,不妨考虑 react-lazyload。虽然 未使用 Intersection Observer,它提供了一种熟悉的延迟方法, 为习惯于使用 React 开发应用的用户加载图片。

每个延迟加载库都有完备的资料,并提供了大量的标记, 适合您的各种延迟加载工作的设计模式。