preface

Pictures for relatively large amount of points on the front page of the APP and so on, at the time of open the commodity display page to add a lot of pictures, if the full quantity loaded directly, under this scenario is bound to cause page performance overhead is too big, bad or caton, the user experience is very bad, the user really need we show all pictures show together? No, the user only sees the content in the viewable area of the browser. Therefore, we can make some optimization from this situation, only display the pictures in the user’s visible area, and then request to display them to the user when the user triggers the scrolling moment

Image lazy loading implementation:

  1. Add a custom attribute to all img tags that need to be displayed: data-src. Do not set the SRC attribute. The value of data-src is the image URL.

  2. When the page is finished loading, we need to fetch the set of elements of all images that need lazy loading, determine if they are in the visible area, and if so, reset the element’s SRC attribute to the address of the real image.

  3. Judgment of visual area: compare the top value of the getBoundingClientRect attribute of the element with the clientHeight of the page. If the top value is less than the clientHeight, it indicates that the element appears in the visual area.

  4. When the user scrolls the window, the BoundingClientRect property of each element should be used to determine if the element is in the viewable area. If it is in the viewable area, the image will be rendered in the viewable area.

Lazy loading implementation:

<! Load images only in the visual area --> <! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> </body> <script> var viewHeight = document.documentElement.clientHeight; / / visual area highly var viewWidth = document. The documentElement. ClientWidth; / / the width of the visual area function the lazyload () {/ / to get all the lazy loading pictures let eles = document. QuerySelectorAll (' img/data - SRC '); / / to get the property name of data - SRC console. The log (' for all of the information, eles) Array. The prototype. The forEach. Call (eles, function (item, index) {let the rect. if (item.dataset.src === '') { return; } rect = item.getBoundingClientRect(); Console. log(' Return the size of the element and its position relative to the viewport ', rect) // Once the picture is in viewport, If (rect.bottom >= 0 &&rect. top < viewHeight) {! function () { let img = new Image(); img.src = item.dataset.src; img.onload = function () { item.src = img.src; } item.removeAttribute('data-src'); } (); } }) } lazyload(); </script> </html>Copy the code

In the above code, we have preliminarily completed lazy image loading, but as we all know, the event of Scroll will be triggered many times when the user scrolls the mouse, which will also lead to a sharp decline in our performance, so this leads to our hybrid anti-shake function to optimize our performance:

function debounce(fn, gapTime) {
        let timer = null;
        return function () {
            if (timer) {
                clearTimeout(timer);
                timer = null;
            }
            timer = setTimeout(function () {
                fn();
            }, gapTime)
        }
    }
Copy the code

Finally post the full code:

<! Load images only in the visual area --> <! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, Word-wrap: break-word! Important; "> <title>Document</title> </head> <body> height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> <img style="width: 250px; height: 250px; background-color: grey; display: block;" data-src="./img/test01.PNG" alt=""> </body> <script> var viewHeight = document.documentElement.clientHeight; / / visual area highly var viewWidth = document. The documentElement. ClientWidth; Console. log(' Height of visualized area ', viewHeight) console.log(' width of visualized area ', viewWidth) let imgDom = document.getElementById('img'); console.log(window.getComputedStyle(imgDom, null).color); / / used to take all the function of the lazyload () {/ / to get all the lazy loading pictures let eles = document. QuerySelectorAll (' img/data - SRC '); / / to get the property name of data - SRC console. The log (' for all of the information, eles) Array. The prototype. The forEach. Call (eles, function (item, index) {let the rect. if(item.dataset.src === '') { return; } rect = item.getBoundingClientRect(); Console. log(' Return the size of the element and its position relative to the viewport ', rect) // Once the picture is in viewport, If (rect.bottom >= 0 &&rect. top < viewHeight) {! function () { let img = new Image(); img.src = item.dataset.src; img.onload = function () { item.src = img.src; } item.removeAttribute('data-src'); } (); } }) } lazyload(); / / add the scroll event trigger picture loading the document. The addEventListener (' scroll 'debounce (the lazyload, 500), false); Function debounce(fn, gapTime) {let timer = null; return function() { if(timer) { clearTimeout(timer); timer = null; } timer = setTimeout(function() { fn(); }, gapTime) } } </script> </html>Copy the code