js 实现图片懒加载(延迟加载)

图片懒加载(图片延迟加载):当图片不在浏览器可视区域中时(即我们此时看不见图片),我们可以先不请求图片资源,当图片出现在浏览器可视区域中时再加载资源。

实现思路

1.结构中,我们用一个盒子包裹着图片(在图片不展示的时候,可以占据着这个位置,并且设置默认的背景图或者背景颜色)

2.最开始,img的src中不设置任何的图片地址,把图片的真实地址设置给自定义属性true-img(最开始不展示图片:可以让图片隐藏)

3.当浏览器窗口完全展示到图片位置的时候,我们再去加载真实图片,并且让其显示出来(第一屏幕中的图片一般都会延迟加载,来等待其它资源先加载完)

单张图片懒加载

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        * {
          padding: 0;
          margin: 0;
        }
        html,body {
          width: 100%;
          height: 100%;
        }
        #box {
          width: 300px;
          height: 200px;
          margin: 800px auto;
        }
        img {
          width: 100%;
          height: 100%;
        }
      </style>
</head>
<body>
    <div id="box">
        <img src="img/default.jpg" true-img="img/1.jpg" alt="">
    </div>
</body>
</html>
<script src="utils.js"></script>
<script>
    var box=document.getElementById('box');
    var img=document.getElementsByTagName("img")[0];
    function check(){
        //滚动条一滚动就触发window.onscroll,为了避免重复加载图片,给img加一个flag属性,成功加载图片后将其值设为true
        if(img.flag){
            return;
        }
        let boxH=box.offsetHeight;//当前图片盒子的总高度
        let boxT=utils.offset(box).top;//获取当前图片盒子距离body的上偏移量
        let winH=utils.win('clientHeight');//获取当前浏览器的可视区域的高度(一屏高)
        let winT=utils.win('scrollTop');//获取当前浏览器滚动条的卷曲的高度
        //图片盒子下边框与浏览器可视区域的下边框重合时,图片完全显示
        //早一些显示图片:winH+winT >= boxT
        if(winH+winT >= boxH+boxT){
            let trueImg=img.getAttribute("true-img");
            //let newImg=document.createElement('img');//创建一个img标签
            let newImg=new Image;//动态创建一个img标签用来检测当前图片的真实路径是否有效
            newImg.arc=trueImg;//把真实的路径给检测的img去请求
            //如果请求到了图片,onload才会执行(如果当前路径是正确的,那onload对应的函数就会执行)
            newImg.onload=function(){
                img.src=trueImg;
                img.flag=true;
                fadeIn(img);//渐入
            }
            //如果请求失败,onerror执行(如果当前路径是错误的,那onerror对应的函数就会执行)
            newImg.onerror=function(){
                //可以给当前图片附一张默认的加载错误图片
                img.src='img/10.jpg';
                img.flag=true;
            }
        }
        function fadeIn(img){
            img.style.opacity=0.01;
            let opacity=Number(img.style.opacity);
            let timer=setInterval(()=>{
                opacity+=0.01;
                img.style.opacity=opacity;
                if(opacity>=1){
                    clearInterval(timer);
                }
            },17);
        }
    }
    window.onscroll=check;
</script>

多张图片懒加载

<head>
	<style>
        * {
            padding: 0;
            margin: 0;
        }
        div {
            margin: 500px auto;
            width: 300px;
        }
        img {
            display: block;
            margin: auto;
            width: 300px;
            height: 200px;
            margin-bottom: 10px;
        }
    </style>
</head>

<body>
    <div>
        <img src="./img/default.jpg" trueImg = "./img/1.jpg" alt="">
        <img src="./img/default.jpg" trueImg = "./img/2.jpg" alt="">
        <img src="./img/default.jpg" trueImg = "./img/3.jpg" alt="">
        <img src="./img/default.jpg" trueImg = "./img/4.jpg" alt="">
        <img src="./img/default.jpg" trueImg = "./img/5.jpg" alt="">
        <img src="./img/default.jpg" trueImg = "./img/6.jpg" alt="">
    </div>
    
    <script src="utils.js"></script>
    <!-- <script src="">
        //如果写了src,内部所有代码都会失效
    </script> -->
    <script>
        var imgs=document.getElementsByClassName("bg");//具有映射关系
        let winH = utils.win('clientHeight'); // 当前屏幕的高度(浏览器可视区域高度)

        // 此方法每执行一次,就会把每一个图片都判断一下要不要显示
        function dealy(){
            //当函数执行的时候,循环每一张图片,然后判断每一张图片是否需要加载
            for (var i = 0; i < imgs.length; i++) {
                dealyImg(imgs[i])
            }
        }
        function dealyImg (img){
            /* if(img.flag){
                return;
            } */
            let curH = img.offsetHeight; // 图片的自身高度
            let curT = utils.offset(img).top; // 图片相对于body的上偏移量
            let winT = utils.win('scrollTop'); // 浏览器滚动条卷去的高度
            if(winH+winT >= curH+curT){
                let address = img.getAttribute('trueImg');
                let newImg = new Image;
                newImg.src = address;
                newImg.onload = function(){
                        img.src = address;
                    	// img.flag=true;
                    	img.className="";
                        newImg = null;
                        fadeIn(img);
                }
            }
        }
        function fadeIn(img) {
            img.style.opacity = 0.05;
            let cur = parseFloat(img.style.opacity);
            let timer = setInterval(function () {
                cur += 0.05;
                img.style.opacity = cur;
                if (cur >= 1) {
                    clearInterval(timer)
                }

            }, 50)
        };
        dealy(); // 页面初始化的时候,要把第一屏的图片展示出来
        window.onscroll = dealy;
    </script>

utils.js

let utils=(function(){
    /* 获取盒子距离body的偏移量 */
    function offset(ele) {
        let left = ele.offsetLeft;
        let top = ele.offsetTop;
        let parent = ele.offsetParent;
        while (parent !== document.body) {
            left += parent.offsetLeft + parent.clientLeft;
            top += parent.offsetTop + parent.clientTop;
            parent = parent.offsetParent;
        }
        return {
            left,
            top
        }
    }
    /* 设置或者获取浏览器的某些属性 */
    function win(attr,value){
        if(value==undefined){
            return document.documentElement[attr] || document.body[attr];
        }
        document.documentElement[attr]=value;
        document.body[attr]=value;
    }
    return {
        offset,
        win
    }
})();
上一篇:javascript 时间版运动框架案例


下一篇:【JavaScript】条件运算符也称‘三元运算符‘的介绍与使用