通过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


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

绿园匠 陶瓷花盆简约中国风创意家用客厅室外阳台室内绿植花卉绿萝发财树蝴蝶兰花盆 花瓣大白 特大号
¥44.33
修年堂 炒酸枣仁100g/罐 炒山熟酸栆仁茶 好睡眠精选中药材助力改善养生炒酸枣仁
¥41.20
lassrik水凝胶鼻膜贴鼻贴膜水凝胶鼻贴男女老少通用鼻周抖音同款 1盒体验装
¥45.20
动感者 D-201电脑音响多媒体蓝牙音箱低音炮有源台式机桌面有线小钢炮手机笔记本 蓝牙版黑白
¥35.60
Sweetcolor解胶剂套装溶解剂卸除甲片假指甲贴
¥42.00
康恩贝儿童维生素C咀嚼片60片水果味儿童成人孕妇乳母vc维c维他命C补充VC 儿童维C1瓶
¥26.80
纳爱斯 尿不湿纸尿裤婴儿L44片(8-12kg)婴童尿片轻薄透气干爽防漏不漏尿
¥38.50
闪魔 红米note10pro钢化膜 高清防爆防摔手机保护膜 【加强版^高清抗指纹】2片装+神器 贴坏贴歪免费补发
¥15.80