图片预加载

通过监听load事件实现图片预加载

window.onload=function(){ // 这里的onload属性 可以使里面代码等页面完全加载完在执行
    var img=document.querySelector("img"); // 这样并不好 万一图片很多 就需要一直等待
    console.log(img.width);
}
第一版

这版只是简单理解以下onload 实际结果是错误的 不能用

init();

function init() {
    var arr = [];
    for (var i = 2; i < 80; i++) { // 循环是同步的 但速度很快
        var img = new Image();
        img.src = "./img/" + i + "-.jpg";

        img.onload = function () { // onload加载时异步的
            arr.push(this); // this是当前加载的图片 
            if (arr.length >= 78) {
                loadFinish(arr); // 没有图片的时候
            }
            document.body.appendChild(this);
            console.log(img) // 在每一张图片加载完成后 img已经被改成了最后一张 所以每次都打印最后一张
        }

    }
}
function loadFinish(arr) {
    arr.forEach(function (item) {
        console.log(item.src); // 由于加载是异步的 所以 图片并不是按照想要的顺序被push进数组的 而是谁先加载完 谁就进数组 所以不可以用这种办法哦
    })
}
第二版

我们想得到的是 加载完第一张图在加载第二张图 类似下面这样!

var arr = [];
var img = new Image();
img.src = "./img/2-.jpg";
img.onload = function () {
    arr.push(this);
    var img1 = new Image();
    img1.src = "./img/3-.jpg";
    img1.onload = function () {
        arr.push(this);
        var img2 = new Image();
        img2.src = "./img/4-.jpg";
        img2.onload = function () {
            arr.push(this);
            var img3 = new Image();
            img3.src = "./img/5-.jpg";
            img3.onload = function () {
                ...
            }
        }
    }
}

当然我们不能按照上述办法这么写 😃

下面这个办法 好像可以实现了 但是还不够优雅

var num=2,arr=[];  // 一共放了从2-79这么多张图 所以从2开始
init();
function init(){
    var img=new Image();  
    img.src="./img/"+num+"-.jpg";
    img.addEventListener("load",loadHanlder); // 这张图加载完了 进入函数
}

function loadHanlder(e){
    arr.push(this); // 将每张图push到数组里
    num++; // 修改img的src属性 再次出发监听事件
    if(num>79){
        loadFinish(arr); // 直到后面没有图片要加载了 跳出函数
        return;
    }
    var img=new Image(); 
    img.src="./img/"+num+"-.jpg"; // 这里的img变量会被不停的修改src
    img.addEventListener("load",loadHanlder)  // 再进来这个函数
    img.addEventListener("error",errorHanlder);
}

function errorHanlder(e){
    console.log(e);
}

function loadFinish(arr){
    arr.forEach(function(item){
        console.log(item.src);
    })
}
第三版

根据事件中的this指向 减少代码冗余

var num=2,arr=[]
init();
function init(){
    var img=new Image();
    img.addEventListener("load",loadHandler);
    img.src="./img/"+num+"-.jpg"; 
}

function loadHandler(e){
    // 把当时加载图片复制一份放在数组中,这个复制的图片就是当时这个地址的图片
    arr.push(this.cloneNode(false));
    num++;
    if(num>79){
        this.removeEventListener("load",loadHandler);
        loadFinish(arr);
        return;
    }
    this.src="./img/"+num+"-.jpg";  // 事件的回调函数中 this指向被监听的元素 所以这里的this就是init函数中的img 可以直接修改img的src 让他再次进入loadHander函数!
}

function loadFinish(arr){
    arr.forEach(function(item){
        console.log(item.src);
    })
}
第四版

把上面的封装出来

var yee=(function(){
    return{
        loadImage:function(arr,callback,basePath){ // 三个参数 图片名的数组 回调函数 相同的路径
            if(typeof basePath==="string"){
                arr=arr.map(function(item){
                    return basePath+item;
                })
            }
            var img=new Image(); // 这是一个图片 图片的src改变 会重新加载 执行loadHandler函数
            img.addEventListener("load",this.loadHandler);  // 这里的this是yee这个对象
            img.addEventListener("error",this.loadHandler)
            img.resultArr=[]; 
            img.num=0; // arr的索引
            img.arr=arr; // 要在监听的回调函数中取到arr 所以存在img属性上
            img.self=this; // 低耦合
            img.callback=callback;
            img.src=arr[0]; // 第一次的src是第一张图
        },
        loadHandler:function(e){
            if(e.type!=="error") this.resultArr.push(this.cloneNode(false)); // 如果没有错误 将每一个img的复制品push到数组里
            this.num++; // 改变地址 准备执行下一次
            if(this.num>this.arr.length-1){ // 如果到了数组的最后一项
                this.removeEventListener("load",this.self.loadHandler); // 这里的this是img 侦听里的回调函数的this指向被侦听的元素 如果想要在这里移除侦听 需要保存上面的this 也就是yee对象
                if(this.callback){ // 如果存在callback函数
                    this.callback(this.resultArr.slice()); // 复制一个最终数组
                }else{
                    var evt=new Event("Load_image_Finish"); // 如果没有callback函数 用自定义事件的属性抛发出去
                    evt.resultArr=this.resultArr; // 事件添加resultArr属性 携带最终的数组(这里为什么不用复制?)
                    document.dispatchEvent(evt);// 抛发出事件 被侦听的地方会收到
                }
                this.resultArr=null;
                this.self=null;
                this.callback=null;
                this.arr=null;
                return;
            }
            this.src=this.arr[this.num]; // 按照arr里的顺序 修改这个图片的src属性 img的src属性被修改 将触发监听 回到上面的函数
        }
    }
})()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值