preface
For the home page APP with a large number of pictures, you need to add a large number of pictures when opening the commodity display page. In this scenario, if you directly load the full amount, it will inevitably lead to excessive page performance consumption, white screen or Caton, and the user experience is very bad. Do users really need us to display all the pictures together? In fact, it's not. What users see is the content of the browser's visual area. Therefore, from this situation, we can make some optimization to display only the pictures in the user's visual area. When the user triggers scrolling, we can request to display them to the user
Implementation of image lazy loading:
-
Add a custom attribute to all img tags that need to be displayed: Data src. At the same time, do not set the src attribute. The value of data src is the image url.
-
After the page is loaded, we need to get the element set of all the pictures that need to be loaded lazily, judge whether it is in the visual area, and if it is in the visual area, reset the src attribute value of the element to the address of the real picture.
-
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 clientHeight, it indicates that the element appears in the visual area.
-
When the user scrolls the window, you should judge whether the element appears in the visual area through the BoundingClientRect attribute of each element. If it is in the visual area, the rendered image is displayed in the visual area.
Implementation of lazy loading:
<!-- Load pictures only in the visualization area --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <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; // Height of visualization area var viewWidth = document.documentElement.clientWidth; // Width of visualization area function lazyload() { //Get all the pictures to be loaded lazily let eles = document.querySelectorAll('img[data-src]'); // Get the attribute with data Src in the attribute name console.log('Get all the information', eles) Array.prototype.forEach.call(eles, function (item, index) { let rect; if (item.dataset.src === '') { return; } rect = item.getBoundingClientRect(); // Returns the size of the element and its position relative to the viewport console.log('Returns the size of the element and its position relative to the viewport', rect) //As soon as the picture enters the visual area, it is loaded dynamically 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>
In the above code, we have initially completed the lazy loading of pictures, but we all know that 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. Therefore, 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) } }
Finally, post the complete code:
<!-- Load pictures only in the visualization area --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <img id="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; // Height of visualization area var viewWidth = document.documentElement.clientWidth; // Width of visualization area console.log('Height of visualization area', viewHeight) console.log('Width of visualization area', viewWidth) let imgDom = document.getElementById('img'); console.log(window.getComputedStyle(imgDom, null).color); // To get all the function lazyload () { //Get all pictures to be loaded lazily let eles = document.querySelectorAll('img[data-src]'); // Get the attribute with data Src in the attribute name console.log('Get all the information', eles) Array.prototype.forEach.call(eles, function(item, index) { let rect; if(item.dataset.src === '') { return; } rect = item.getBoundingClientRect(); // Returns the size of the element and its position relative to the viewport console.log('Returns the size of the element and its position relative to the viewport', rect) //As soon as the picture enters the visual area, it is loaded dynamically 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 scroll event to trigger picture loading document.addEventListener('scroll', debounce(lazyload, 500), false); // Continuous optimization through function anti chattering: function debounce(fn, gapTime) { let timer = null; return function() { if(timer) { clearTimeout(timer); timer = null; } timer = setTimeout(function() { fn(); }, gapTime) } } </script> </html>
Nuggets link:
- https://juejin.cn/post/6977945074885722126