js - 图片懒加载,优化高度限制

优化高度限制
预览

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>图片懒加载 - 不限高度</title>
    <style>
        img {
            display: block;
            width: 600px;
        }
    </style>
</head>

<body>

</body>
<script>
    let imgs = [
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901540/o_201216091158wugengji%20(1).jpg",
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_2012161143007aec54e736d12f2e07615a764cc2d56285356844.jpg",
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_201216114728013deab63aa80376386b4f983a184f6d.jpg",
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_2012161146434e4a20a4462309f774fbcd07710e0cf3d7cad60b.jpg",
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_201216114719be34b4c27d1ed21b5e262e84ab6eddc450da3f07.jpg",
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901540/o_201216091241wugengji%20(2).jpg",
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_2012161147562c6e26d3d539b60082cb6c6aec50352ac75cb702.jpg",
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901540/o_201216091213wugengji%20(3).jpg",
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_2012161146434e4a20a4462309f774fbcd07710e0cf3d7cad60b.jpg",
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901540/o_201216091229wugengji%20(4).jpg",
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_201216114629039598aa570dca3b.jpg",
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_2012161148532dcca28f8c5494ee50cec76029f5e0fe98257eea.jpg",
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_2012161149075469531d74d1b.jpg",
        "https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_201216114949859ea13533fa828b32c579a2fe1f4134960a5a29.jpg"
    ], loadingImg = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fhbimg.b0.upaiyun.com%2F079631e90e8871989842d35305b636f46761d4a5fe5-YizIOH_fw658&refer=http%3A%2F%2Fhbimg.b0.upaiyun.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1627726169&t=6de518bc2437fb39d6d30d7b4cfb1682';
    // document.body.innerHTML = imgs.map(v => `<img onload="imgLoad(this)" data-src="${v}" src="${loadingImg}" />`).join('');  //  将新创建的元素及其内容添加到DOM中
    document.body.innerHTML = imgs.map(v => `<img data-src="${v}" src="${loadingImg}" />`).join('');  //  将新创建的元素及其内容添加到DOM中

    function lazyLoad(delay = 500) {
        let imgLoad = (img, i) => {
            // console.log('\nimgLoad\nheight:', img.height, '\nindex:', i, '\ndata-src === src:', img.getAttribute('data-src') === img.currentSrc, '\narguments:', arguments)
            init()
            img.onload = null
        },
            imgDoms = document.querySelectorAll('img'),
            /**
            todo:
                当前图片初始化是从第一个开始,若滚动后刷新,任然是从第一个开始,不是从可视区域的第一个开始显示。
                考虑缓存和仅优化首次加载并不需要完善。
                完善思路,判断不仅判断offsetTop,同时判断bottom
            */
            init = () => {
                let H = document.documentElement.clientHeight,//获取可视区域高度
                    S = document.documentElement.scrollTop || document.body.scrollTop;
                for (var i = 0, v = imgDoms[i]; i < imgDoms.length; i++ , v = imgDoms[i]) {
                    let dataSrc = v.getAttribute('data-src'),
                        isloaded = v.getAttribute('data-loaded') // delay 导致 dataSrc !== v.currentSrc 判断加载状态延迟,滚动重复触发,isloaded提前标记状态
                    if (!isloaded && H + S > v.offsetTop) {
                        // 未加载且在显示区范围初始化 
                        v.setAttribute('data-loaded', true)
                        setTimeout(() => {
                            // console.log('\nindex:', i, '\nheight:', v.height, '\nisloaded:', isloaded, '\ndata-src=currentSrc:', v.getAttribute('data-src') === v.currentSrc, '\nclientHeight:', H, '\nscrollTop:', S, '\noffsetTop:', v.offsetTop)
                            v.src = dataSrc
                            v.onload = imgLoad.bind(null, v, i) // 下一个初始化,init放在img onload保证图片显示后高度已经变化,下一项offsetTop准确
                            // if (i === 0) // 测试imgLoad 是否清除
                            //     setTimeout(() => {
                            //         v.src = loadingImg
                            //     }, 1000)
                        }, delay)
                        break;
                    } else if (!isloaded) {
                        // 未加载不在显示区范围,退出初始话,开始监听滚动
                        scrollLoad()
                        break;
                    }
                }
            },
            scrollLoad = () => {
                window.onload = window.onscroll = function () { //onscroll()在滚动条滚动的时候触发
                    loadone();
                }
            },
            loadone = (isInit = false) => {
                var H = document.documentElement.clientHeight;//获取可视区域高度
                var S = document.documentElement.scrollTop || document.body.scrollTop;
                for (var i = 0, v = imgDoms[i]; i < imgDoms.length; i++ , v = imgDoms[i]) {
                    let dataSrc = v.getAttribute('data-src'),
                        isloaded = v.getAttribute('data-loaded') // delay 导致 dataSrc !== v.currentSrc 判断加载状态延迟,滚动重复触发,isloaded提前标记状态
                    if (!isloaded && H + S > v.offsetTop) {
                        v.setAttribute('data-loaded', true)
                        setTimeout(() => {
                            v.src = dataSrc
                        }, delay)
                        break;
                    }
                }
            }
        init()
    }

    lazyLoad()
    
</script>

</html>

已知高度|有高度限制,不设高度会导致懒加载无效
预览

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>图片懒加载 - 已知高度</title>
    <style>
        img {
            display: block;
            width: 100%;
            height: 300px;
            margin-bottom: 20px;
        }
    </style>
</head>

<body>
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901540/o_201216091158wugengji%20(1).jpg" alt="">
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_2012161143007aec54e736d12f2e07615a764cc2d56285356844.jpg"
        alt="">
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_201216114728013deab63aa80376386b4f983a184f6d.jpg"
        alt="">
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_2012161146434e4a20a4462309f774fbcd07710e0cf3d7cad60b.jpg"
        alt="">
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_201216114719be34b4c27d1ed21b5e262e84ab6eddc450da3f07.jpg"
        alt="">
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901540/o_201216091241wugengji%20(2).jpg" alt="">
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_2012161147562c6e26d3d539b60082cb6c6aec50352ac75cb702.jpg"
        alt="">
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901540/o_201216091213wugengji%20(3).jpg" alt="">
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_2012161146434e4a20a4462309f774fbcd07710e0cf3d7cad60b.jpg"
        alt="">
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901540/o_201216091229wugengji%20(4).jpg" alt="">
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_201216114629039598aa570dca3b.jpg" alt="">
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_2012161148532dcca28f8c5494ee50cec76029f5e0fe98257eea.jpg"
        alt="">
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_2012161149075469531d74d1b.jpg" alt="">
    <img data-src="https://images.cnblogs.com/cnblogs_com/zc-lee/1901644/o_201216114949859ea13533fa828b32c579a2fe1f4134960a5a29.jpg"
        alt="">
</body>
<script>
    // 仅适用于已知img height 不设高度会导致懒加载无效
    var imgs = document.querySelectorAll('img');

    //offsetTop是元素与offsetParent的距离,循环获取直到页面顶部
    function getTop(e) { // ???
        var T = e.offsetTop;
        while (e = e.offsetParent) {
            T += e.offsetTop;
        }
        return T;
    }

    function lazyLoad(imgs) {
        var H = document.documentElement.clientHeight;//获取可视区域高度
        var S = document.documentElement.scrollTop || document.body.scrollTop;
        for (var i = 0; i < imgs.length; i++) {
            // if (H + S > getTop(imgs[i])) {
            if (H + S > imgs[i].offsetTop) {
                imgs[i].src = imgs[i].getAttribute('data-src');
            }
        }
    }

    window.onload = window.onscroll = function () { //onscroll()在滚动条滚动的时候触发
        lazyLoad(imgs);
    }
</script>

</html>
posted @ 2021-07-02 14:07  zc-lee  阅读(232)  评论(0编辑  收藏  举报