Image lazy loading (1)

What is lazy loading of images

The image resource is requested when we scroll down. This is the effect we want to achieve this time. When entering the page, only the image resource in the visible area is requested, which is lazy loading.

For example, if we load a page, the page is very long and long enough to fit in the visible area of ​​our browser, then lazy loading is to load the contents of the visible area first, and other parts are loaded when entering the visible area.

This function is very common. If you open Taobao's homepage and scroll down, you will see that pictures are constantly loading; if you search for pictures in Baidu, there will be thousands of results, and it is impossible to load all of them at once. Yes, the very important reason is that there will be performance problems. You can check it in Network. When the page scrolls, you will see the pictures loaded one by one.

 

Why do pictures lazy loading

Lazy loading is a way to optimize web page performance, which can greatly improve user experience. Take pictures, for example. Pictures have always been the main culprit affecting the performance of web pages. Now it is very common for a picture to exceed a few megabytes. If you request all the image resources every time you enter the page, then the user may have already left after the image is loaded. Therefore, we need to load lazily, when entering the page, only request the image resources of the visible area.

There are two points to sum up:

1. All loading will affect the user experience

2. A waste of user traffic, some users do not look like all of them, loading all will consume a lot of traffic.

Principle of lazy loading

The image tag is the img tag. The source of the image is mainly the src attribute. Whether the browser initiates a request to load the image is determined by whether there is an src attribute.

So you can start with the src attribute of the img tag, and don't assign a value to the src attribute of the img tag before entering the visible area.

Lazy loading implementation

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            display: flex;
            flex-direction: column;
        }
        img {
            width: 100%;
            height: 300px;
        }
    </style>
</head>
<body>
    <div>
        <img >"https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657907683.jpeg">
        <img >"https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657913523.jpeg">
        <img >"https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657925550.jpeg">
        <img >"https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657930289.jpeg">
        <img >"https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657934750.jpeg">
        <img >"https://cdn.suisuijiang.com/ImageMessage/5adad39555703565e79040fa_1590657918315.jpeg">
    </div>
</body>

</html>

Listen to the scroll event to determine whether the element enters the viewport

const imgs = [...document.getElementsByTagName('img')];
 let n = 0;

 lazyload();

 function throttle(fn, wait) {
    let timer = null;
    return function(...args) {
        if(!timer) {
            timer = setTimeout(() => {
                timer = null;
                fn.apply(this, args)
            }, wait)
        }
    }
 }
  
 function lazyload() {
    var innerHeight = window.innerHeight; 
    var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    for(let i = n; i < imgs.length; i++) {
        if(imgs[i].offsetTop < innerHeight + scrollTop) {
            imgs[i].src = imgs[i].getAttribute("data-src");
            n = i + 1;
        }
        
    }
 }
 window.addEventListener('scroll', throttle(lazyload, 200));

There may be the following problems:

 

Each swipe must execute a loop, if there are more than 1000 pictures, the performance will be poor

Every time scrollTop is read, it will cause backflow

scrollTop is related to the nesting relationship of DOM and should be obtained according to getboundingclientrect

Refresh when you slide to the end, you will see all the pictures are loaded

 

IntersectionObserver

The Intersection Observer API provides a way to asynchronously observe the changes in the intersection of the target element and the ancestor element or the viewport of the top-level document.

Create an IntersectionObserver object, and pass in the corresponding parameters and call back the function. The callback function will be executed when the size of the intersection of the target element and the root element exceeds the threshold.

var observer = new IntersectionObserver(callback, options);

IntersectionObserver is a constructor provided by the browser and accepts two parameters: callback is the callback function when the visibility changes (that is, the callback function will be executed when the target element appears in the element specified by the root option), and option is the configuration Object (this parameter is optional).

The returned observer is an observer instance. The observe method of the instance can specify which DOM node to observe.

For specific usage, please check the  MDN document

const imgs = [...document.getElementsByTagName('img')];
// 当监听的元素进入可视范围内的会触发回调
 if(IntersectionObserver) {
     // 创建一个 intersection observer
     let lazyImageObserver = new IntersectionObserver((entries, observer) => {
         entries.forEach((entry, index) => {
             let lazyImage = entry.target;
             // 相交率,默认是相对于浏览器视窗
             if(entry.intersectionRatio > 0) {
                lazyImage.src = lazyImage.getAttribute('data-src');
                // 当前图片加载完之后需要去掉监听
                 lazyImageObserver.unobserve(lazyImage);
             }

         })
     })
     for(let i = 0; i < imgs.length; i++) {
        lazyImageObserver.observe(imgs[i]);
     }
 }

 

Guess you like

Origin blog.csdn.net/weixin_43844696/article/details/107046122