classes_img-lazy-load.js

/*
 * @Author liangjun
 * @LastEditors liangjun
 * @Date 2020-07-17 17:03:41
 * @LastEditTime 2023-06-05 16:48:15
 * @Description 图片懒加载
 */

/**
 * @class ImageLazyLoad
 * @description 图片懒加载,自动读取所有包含option.source属性的图片,将到达窗口的图片src替换为 option.source 属性的真实链接
 * @param {Object} options 懒加载选项
 * @param {String} options.source - 存放图片链接的属性,如:data-lazy
 * @example
 * // <img src="default.png" data-lazy="http://dev-images.qiniu.kuman.com/diurnal/timgNR1M9P5Y.jpg" alt="">
 * const lazyImage = new ImageLazyLoad();
 * // 开启懒加载
 * lazyImage.start();
 * // 关闭懒加载
 * lazyImage.end();
 * // 重新开启懒加载
 * lazyImage.refresh();
 */
export class ImageLazyLoad {
    /**
     * @ignore 不显示这个构造函数文档,和类的参数重复了
     * @param {Object} options 懒加载选项
     * @param {String} options.source - 存放图片链接的属性,如:data-lazy
     */
    constructor(options = {}) {
        this.sourceAttrName = options.source || "data-lazy";
        this.ob = null;
        this.throttle = null;
        this.startLock = false;
    }
    loadImage(img) {
        img.src = img.getAttribute(this.sourceAttrName);
    }
    isInSight(img) {
        const bound = img.getBoundingClientRect();
        const clientHeight = window.innerHeight;
        //如果只考虑向下滚动加载
        //const clientWidth = window.innerWeight;
        return bound.top <= clientHeight + 100; // +100提前加载
    }
    /**
     * @description 开始检测所有图片状态,进行懒加载和滚动监听
     */
    start() {
        if (this.startLock) {
            console.log("lazyload already start");
            return;
        }
        this.scrollListen();
        if ("IntersectionObserver" in window) {
            let imgs = Array.from(
                document.querySelectorAll(`img[${this.sourceAttrName}]`)
            );
            this.ob = new IntersectionObserver((changes) => {
                for (const change of changes) {
                    if (
                        0 < change.intersectionRatio &&
                        change.intersectionRatio <= 1
                    ) {
                        this.loadImage(change.target);
                        this.ob.unobserve(change.target);
                    }
                }
            });
            imgs.forEach((img) => {
                this.ob.observe(img);
            });
        } else {
            window.addEventListener("scroll", this.scrollListen.bind(this));
        }
        this.startLock = true;
    }
    /**
     * @description 停止检测所有图片状态,停止懒加载和滚动监听
     */
    end() {
        this.ob.disconnect();
        window.removeEventListener("scroll", this.scrollListen);
        this.startLock = false;
    }
    /**
     * @description 重新检测所有图片状态,重新懒加载和滚动监听
     */
    refresh() {
        this.end();
        this.start();
    }
    normalLazyLoad() {
        let imgs = Array.from(
            document.querySelectorAll(`img[${this.sourceAttrName}]`)
        );
        imgs.forEach((img) => {
            if (this.isInSight(img)) {
                this.loadImage(img);
            }
        });
    }
    scrollListen() {
        this.normalLazyLoad();
    }
}