通过js代码切入全局实现图片loading效果

项目中有一个图片列表的页面,每个页面大概有几十张图片,图片加载比较慢的时候就都是白屏看起来很不友好,于是就想给图片增加一个loading效果,但是又不想改动原有代码,于是我想了一个通用的方案,通过js代码切入直接全局修改实现图片的loading效果。

经过实验和思考,我最终实现的方案是:在dom加载完毕后,图片加载完成之前,这中间的时刻触发我的操作,操作内容是获取需要进行loading效果的图片元素即img标签,将img的图片地址取出,替换成loading效果的图片,这时新建一个Image对象,将取出的原图片地址通过新建的Image对象去加载图片资源,当图片资源加载完毕之后,把原图地址设置回原来的img元素。说起来有点绕,直接看代码吧。

<script>
    //配置loading中的图片
    let imgLoading = "img/img-loading.gif";
    //配置加载失败的图片
    let imgFail = "img/img-no.jpg";
    //提前加载需要的图片资源
    new Image().src = imgLoading;
    new Image().src = imgFail;

    /**
    * 处理图片方法
    * @param obj 处理的图片元素
    */
    function handleImg(obj){
        obj.onerror = function () {
            obj.src = imgFail
        };
        setTimeout(function() {
            if (!obj.complete) {
                //新建一个临时的图片元素
                let temp = new Image();
                //原图片路径赋值给临时图片元素
                temp.src = obj.getAttribute("src");
                //原图片改成loading图片
                obj.setAttribute("src", imgLoading);
                //临时图片元素设置加载完成回调函数
                temp.onload = function () {
                    obj.src = temp.src
                };
            }
        },1000);
    }

    //dom结构加载完后对所有img节点进行loading处理
    $(document).ready(function(){
        let imgList = document.getElementsByTagName('img');
        for (let img of imgList) {
            handleImg(img)
        }
    });
</script>

将上述代码块放于head标签中,自行配置loading效果的图片和图片加载失败之后显示的图片资源路径,即imgLoading和imgFail两个变量的值。最终效果如图:(第一张图片是正常显示的图片;第二张图片是我的loading状态图,一个挺好看的动图;第三张图片是加载失败之后的图片)

代码解释:
1、代码切入点使用的是$(document).ready(function(){});因为在这一时刻,dom节点已经都加载完毕了,但是图片资源不一定全部加载完毕,符合我方案要求。这一块可以使用下方代码进行测试。

$(document).ready(function(){
    let imgList = document.getElementsByTagName('img');
    for (let img of imgList) {
        img.onload=function(){
            console.log("图片加载结束");
        };
    }
    console.log("document.ready执行结束");
});

2、因为loading状态的图片肯定要早于具体的图片先加载,否则loading图片替换之后还是白屏,没有意义。因此需要如下代码提前加载loading图片资源。

//提前加载需要的图片资源
new Image().src = imgLoading;
new Image().src = imgFail;

3、假如图片加载很快,在1秒内已经加载完毕了,那这个时候就没必要再替换成loading图片,然后再替换回正常图片,按照我的理解,只有那些大于1秒还没加载好的图片才需要loading效果,所以我在handleImg方法里面加了个timeout方法,解决图片会闪一下loading效果的问题。这里的1秒时间可以自定义。

完整的demo见:https://gitee.com/lqccan/blog-demo/tree/master/%E5%89%8D%E7%AB%AF/%E5%9B%BE%E7%89%87loading


觉得内容还不错?打赏个钢镚鼓励鼓励!!👍