10

Lazy loading of first screen optimization

Lazy-Load. It is optimized for the timing of image loading: On some websites with a large amount of images (such as the homepage of e-commerce websites, or group buying websites, small game homepages, etc.), if we try to put all the image resources when the user opens the page After loading, it may cause a blank screen, freezes, etc., because there are too many pictures, and the browser can't handle so many tasks in one go!

purpose

The purpose of lazy loading is an optimized way to load pictures when the picture on the page enters the user's visible range.

It can increase the loading speed of the first screen. After all, the moment the user clicks on the page, only the first screen is presented to him. We only need to load the resource image of the first screen. As for the image below, when the user slides down, it will be the current position. When it is loaded, there is no problem when it is loaded, the performance pressure is also less, and the user experience has not deteriorated.

principle

When the page is initialized,
<img> picture src actually put data-src on the property when the element is in the visible range, put data-src assigned to src property, complete the picture loaded.

// 在一开始加载的时候
<img data-src="http://xx.com/xx.png" src="" />

// 在进入可视范围内时
<img data-src="http://xx.com/xx.png" src="http://xx.com/xx.png" />

Use the background image to achieve the same principle. Put background-image in the visible range and assign src data-src to complete the image loading.

// 在一开始加载的时候
<div
  data-src="http://xx.com/xx.png"
  style="background-image: none;background-size: cover;"
></div>

// 在进入可视范围内时
<div
  data-src="http://xx.com/xx.png"
  style="background-image: url(http://xx.com/xx.png);background-size: cover;"
></div>

Implement a lazy loading

Based on the above implementation ideas, implement a lazy loading by yourself.

Create a new index.html img tags for these pictures:

<head>
  <style>
    .img {
      width: 200px;
      height: 200px;
      background-color: gray;
      margin-bottom: 20px;
    }

    .pic {
      width: 100%;
      height: 100%;
    }
  </style>
</head>
<!-- 图片来自网络,侵删。 -->

<body>
  <div class="container">
    <div class="img">
      <!-- 注意我们并没有为它引入真实的src -->
      <img
        class="pic"
        alt="加载中"
        data-src="https://tse1-mm.cn.bing.net/th/id/OIP.8OrEFn_rKe82kqAWFjTuMwHaEo?pid=Api&rs=1"
      />
    </div>
    <div class="img">
      <img
        class="pic"
        alt="加载中"
        data-src="https://ssl.tzoo-img.com/images/tzoo.94911.0.910013.seoul-nami.jpg?width=1080"
      />
    </div>
    <div class="img">
      <img
        class="pic"
        alt="加载中"
        data-src="https://tse4-mm.cn.bing.net/th/id/OIP.ZitgAuABnwkrGn4lid2ZmQHaEK?pid=Api&rs=1"
      />
    </div>
    <div class="img">
      <img
        class="pic"
        alt="加载中"
        data-src="http://pic34.photophoto.cn/20150315/0034034862056002_b.jpg"
      />
    </div>
    <div class="img">
      <img
        class="pic"
        alt="加载中"
        data-src="http://img.mp.sohu.com/upload/20170724/32d4409f34194b029ed287abf1c99b70_th.png"
      />
    </div>
    <div class="img">
      <img
        class="pic"
        alt="加载中"
        data-src="https://pic6.wed114.cn/20180829/2018082910075991913520.jpg"
      />
    </div>
    <div class="img">
      <img
        class="pic"
        alt="加载中"
        data-src="https://tse4-mm.cn.bing.net/th/id/OIP.PZdPKj3sXEX2jLrepx3MUwHaEo?pid=Api&rs=1"
      />
    </div>
    <div class="img">
      <img
        class="pic"
        alt="加载中"
        data-src="https://pic6.wed114.cn/20180829/2018082910075831439349.jpg"
      />
    </div>
    <div class="img">
      <img
        class="pic"
        alt="加载中"
        data-src="https://pic6.wed114.cn/20180829/2018082910075468043336.jpg"
      />
    </div>
    <div class="img">
      <img
        class="pic"
        alt="加载中"
        data-src="https://tse2-mm.cn.bing.net/th/id/OIP.CRYz5Bv4vylsMh83G4CsLgHaFj?pid=Api&rs=1"
      />
    </div>
  </div>
</body>

In the implementation of lazy loading, there are two key values: one is the current viewable area of , 1607d318154bfe, and the other is element from the top of the viewable area, .

current highly visible area , in modern browsers and above IE9 browser, you can use window.innerHeight property acquisition, use low versions of IE document.documentElment.clientHeight get, here we are compatible in both cases:

const viewHeight = window.innerHeight || document.documentElement.clientHeight;

And the element from the top of the visible area is . Here we use the getBoundingClientRect() method to get the size of the returned element and the position relative to the size. For this API, MDN’s explanation is:

The Element.getBoundingClientRect() method returns the size of the element and its position relative to the viewport.

top attributes is the height relative to the top of the visible area, which is the 0607d318154c8f attribute, which is exactly the distance between the element we need and the top.

In this way, both attributes are obtained.

We use , the height of the current viewable area, greater than or equal to , the height of the element from the top of the viewable area, to determine whether the element has entered the viewable range:

<script>
  // 获取所有的图片标签
  const imgs = document.getElementsByTagName("img");
  // 获取可视区域的高度
  const viewHeight =
    window.innerHeight || document.documentElement.clientHeight;
  // num用于统计当前显示到了哪一张图片,避免每次都从第一张图片开始检查是否露出
  let num = 0;

  function lazyload() {
    console.log("滚动...");
    for (let i = num; i < imgs.length; i++) {
      // 用可视区域高度减去元素顶部距离可视区域顶部的高度
      let distance = viewHeight - imgs[i].getBoundingClientRect().top;
      // 如果可视区域高度大于等于元素顶部距离可视区域顶部的高度,说明元素露出
      if (distance >= 0) {
        // 给元素写入真实的src,展示图片
        imgs[i].src = imgs[i].getAttribute("data-src");
        // 前i张图片已经加载完毕,下次从第i+1张开始检查是否露出
        num = i + 1;
      }
    }
  }

  // 防抖函数
  function debounce(fn, delay = 500) {
    let timer = null;
    return function (...args) {
      if (timer) clearTimeout(timer);
      timer = setTimeout(() => {
        fn.call(this, args);
      }, delay);
    };
  }

  // 是的页面初始化是加载首屏图片
  window.onload = lazyload;
  // 监听Scroll事件,为了防止频繁调用,使用防抖函数优化一下
  window.addEventListener("scroll", debounce(lazyload, 600), false);
</script>

Image Lazy Loading-Online Preview

summary

  • First collect all img in the page (you can also use class ).
  • Get the height of the view, calculate the displayed img , and avoid repeated assignment of src .
  • When sliding the mouse down, it will trigger the onScroll event (anti-shake), and then trigger the calculation of whether to assign src .

Reference


九旬
1.1k 声望1.2k 粉丝