The meaning of lazy image loading

Although modern browsers render a DOM tree. Img does not prevent the DOM TREE from being rendered (the browser will open an HTTP thread to request the image resource file), but after generating the RENDER TREE, the browser will draw the TREE and the image together, which will affect the performance of the page.

  1. If the requested image resources are too many, we can open up only 6 HTTP threads at the same time, so that the image resources are loaded in advance, will affect the request speed of other resources;
  2. When drawing the page for the first time, if you start drawing pictures, also need to consume a lot of time, which also affects the speed of the page opened for the first time.

So in this case:

  1. We usually use lazy loading of images (when we first need to display the location of the image, we use the default image or a blank box to occupy the space, the real image will not load, only after a rendering of the page and scroll to the current area, the real image will load);
  2. We could use base64 (slower, but better than nothing).

getBoundingClientRect

GetBoundingClientRect is used to get a collection of the locations of an element relative to the window. We have top, right, bottom, left, and so on.

clientRect = lazyImageBox.getBoundingClientRect();
Copy the code
  1. Clientrect. top: the distance from the top of the element to the top of the window;
  2. Clientrect. right: The distance from the right of the element to the left of the window;
  3. Clientrect. bottom: The distance from the bottom of the element to the top of the window;
  4. Clientrect.left: The distance from the left of the element to the left of the window.

The bottom of the box is less than or equal to the height of the viewport before loading the image.

let lazyImageBox = document.querySelector('.lazyImageBox'),
    lazyImage = lazyImageBox.querySelector('img');

const singleLazy = function singleLazy() {
    let trueImg = lazyImage.getAttribute('lazy-image');
    lazyImage.src = trueImg;
    lazyImage.onload = () = > {
        // The real image was loaded successfully
        lazyImage.style.opacity = 1;
    };
    lazyImageBox.isLoad = true;
};

const lazyFunc = function lazyFunc() {
    // Prevent repeated processing
    if (lazyImageBox.isLoad) return;
    let A = lazyImageBox.getBoundingClientRect().bottom,
        B = document.documentElement.clientHeight || document.body.clientHeight;
    if(A <= B) { singleLazy(); }};// window.onscroll = lazyFunc; // The default browser listens for the scroll event to be triggered in the fastest response time and executes the lazyFunc method, which is too frequent -> throttling
window.onscroll = throttle(lazyFunc);
Copy the code

IntersectionObserver

IntersectionObserver can automatically “observe” whether an element is visible. The essence of the API is to create a cross between the target element and the viewport, so the API is called “cross Viewer”.

It’s very simple to use.

let ob = new IntersectionObserver(callback, option);
Copy the code

In the above code, IntersectionObserver is the constructor provided by the browser, which takes two arguments: callback is the callback function when visibility changes, and Option is the configuration object (which is optional).

The return value of the constructor is an observer instance. The observe method of the instance specifies which DOM node to observe.

// Start observing

ob.observe(document.getElementById('example'));

// Stop observing
ob.unobserve(element);

// Close the observer
ob.disconnect();
Copy the code

In the above code, the argument to observe is a DOM node object. If you are looking at multiple nodes, you call this method multiple times.

The callback parameter

The viewer’s callback function is called when the visibility of the target element changes.

The callback is usually fired twice. Once when the target element is just entering the viewport (start visible) and once when it is completely out of the viewport (start invisible)

let ob = new IntersectionObserver(changes= > {
    // Changes is an array containing all the listening DOM elements and viewport cross information
    let item = changes[0],
        {
            isIntersecting,
            target
        } = item;
});
Copy the code

The parameters of the callback function (changes) is an array, each member is a IntersectionObserverEntry object. For example, if the visibility of two observed objects changes at the same time, the Changes array will have two members.

IntersectionObserverEntry object

IntersectionObserverEntry observation elements of information, there are eight properties.

1. BoundingClientRect: Rectangle information of the target element. 2. IntersectionRatio: proportion value between intersecting area and target element; 3. IntersectionRect: The rectangular information intersecting the target element and the window (root) can be called the intersecting area; 4. IsIntersecting: Whether the target element is currently visible. The Boolean value can be true. 5. RootBounds: The rectangle information of the root element, without specifying that the root element is the rectangle information of the current window; 6. Target: The target element of observation; 7. Time: Return a timestamp from the time of IntersectionObserver to the time when the IntersectionObserver was fired.Copy the code

IntersectionRect/boundingClientRect: less than or equal to zero when not visible;

Option object

The second argument to the IntersectionObserver constructor is a configuration object. It can set the following properties.

The threshold attribute determines when to fire the callback function. It is an array, and each member is a threshold value. The default value is [0], that is, when the intersectionRatio reaches 0, the callback function is triggered.

The user can customize the array. For example, [0, 0.25, 0.5, 0.75, 1] means that the callback function is triggered when the target element is 0%, 25%, 50%, 75%, and 100% visible.

let lazyImageBox = document.querySelector('.lazyImageBox'),
    lazyImage = lazyImageBox.querySelector('img');
const singleLazy = function singleLazy() {
    let trueImg = lazyImage.getAttribute('lazy-image');
    lazyImage.src = trueImg;
    lazyImage.onload = () = > {
        lazyImage.style.opacity = 1;
    };
};
// Use a DOM listener IntersectionObserver to listen for information about one or more DOM elements intersecting with the visible window
let ob = new IntersectionObserver(changes= > {
    // Changes is an array containing all the listening DOM elements and viewport cross information
    let item = changes[0],
        {
            isIntersecting,
            target
        } = item;
    if (isIntersecting) {
        // Fully appear in the viewport
        singleLazy();
        ob.unobserve(lazyImageBox); // After loading the real image, remove the listening on the box}}, {threshold: [1]}); ob.observe(lazyImageBox);Copy the code

conclusion

IntersectionObserver is a new browser API, which can facilitate the lazy loading of images. However, getBoundingClientRect has better compatibility than IntersectionObserver. Since IE is not compatible, these functions should be implemented in IE. Again, I’m going to use getBoundingClientRect based on scroll events.