首頁 >web前端 >js教程 >jQuery如何實現預先載入圖片功能

jQuery如何實現預先載入圖片功能

藏色散人
藏色散人原創
2019-05-27 15:40:372994瀏覽

最近要用javascript做一個動畫功能,為了確保動畫在播放的時候能夠順利和平滑,我需要對所用到的圖片素材進行預加載,下面跟大家分享一下我實現這個功能的過程

jQuery如何實現預先載入圖片功能

單一圖片預先載入

目前最常見的實作方式如下

function preloadImg(url) {
    var img = new Image();
    img.src = url;
    if(img.complete) {
        //接下来可以使用图片了
        //do something here
    }
    else {
        img.onload = function() {
            //接下来可以使用图片了
            //do something here
        };
    }
}

首先實例化一個Image對象賦值給img,然後設定img.src為參數url指定的圖片位址,接著判斷img的complete屬性,如果本地有這張圖片的緩存,則該值為true,此時我們可以直接操作這張圖片,如果本機沒有緩存,則該值為false,此時我們需要監聽img的onload事件,把對img的操作放在onload的回調函數裡面,經過測試,這種方案基本上能夠兼容目前所有瀏覽器

多圖片預先載入

很多場景下,單一圖片預先載入並不能滿足我們的需求,因為像動畫這種功能通常都會有很多的圖片素材,接下來我們就在原來單一圖片預先載入的基礎上來改進我們的函數

function preloadImg(list) {
    var imgs = arguments[1] || [],    //用于存储预加载好的图片资源
        fn = arguments.cal    lee;
    if(list.length == 0) {
        return imgs;
    }
    var img = new Image();
    img.src = list[0];
    if(img.complete) {
        imgs.push(img);
        list.shift();
        fn(list, imgs);
    }
    else {
        img.onload = function() {
            imgs.push(img);
            list.shift();
            fn(list, imgs);
        };
    }
}
var list = [......],    //此处省略一万个字符
    imgs = preloadImg();

因為幀動畫可能需要保證每一幀動畫所用的圖片的順序,所以我在這段程式碼中使用遞歸的方式,在上一張加載完成之後再去加載下一張圖片,每加載一張圖片,就把這張圖片資源存儲到imgs數組中,並且把這張圖片的地址從地址數組list中去掉,當list中已經沒有位址的時候跳出遞歸,並返回imgs數組

設想很美好,現實很殘酷,這段程式碼有2個不能忍受的問題

首先,我很有可能拿不到最後返回的imgs數組,因為只要有圖片在本地沒有緩存,imgs的存儲操作都會放到onload的回調事件中,而事件監聽也屬於javascript中異步操作的一種,在綁定完onload事件的回調函數後,preloadImg函數就執行結束了,沒有任何回傳值,外部imgs變數接收到的值為undefined,只有在所有圖片都有本地快取的情況下,外部imgs變數才能順利拿到儲存了全部預載入圖片資源的陣列

在載入完一張圖片之後才去載入下一張,整個預先載入圖片的過程所需要的時間相對會比較長,使用者體驗會降低,而且本來非同步操作具體速度快的特性,這樣的實作方式等於完全棄置了onload異步的這個特性

多圖片預先載入(改進版)

這次我們直接把一個空數組作為參數傳進函數,圖片全部儲存到這個數組裡面,下面是改進後的函數代碼(假設我們可以使用jQuery)

function preloadImg(list,imgs) {
    var def = $.Deferred(),
        len = list.length;
    $(list).each(function(i,e) {
        var img = new Image();
        img.src = e;
        if(img.complete) {
            imgs[i] = img;
            len--;
            if(len == 0) {
                def.resolve();
            }
        }
        else {
            img.onload = (function(j) {
                return function() {
                    imgs[j] = img
                    len--;
                    if(len == 0) {
                        def.resolve();
                    }
                };
            })(i);
            img.onerror = function() {
                len--;
                console.log('fail to load image');
            };
        }
    });
    return def.promise();
}
var list = [......],    //此处省略一万个字符
    imgs = [];
$.when(preloadImg(list, imgs)).done(
    function() {
        //预加载结束
        //do something here
    }
);

在分別給每一個img綁定onload的回調函數時採用了閉包的方式,目的是為了保存住當前的遞增變數i,如果不這麼做,結果將會是list位址中沒有本地快取的圖片都儲存到imgs的最後一個元素上

這次每載入一張圖片,我們並沒有把這張圖片的位址從list數組中去掉,這樣後續需要使用list數組的資料時就能夠順利取得到

在這次的程式碼中,我們引入了jQuery的Deferred對象,這樣更方便我把握整個預載圖片的過程

以上是jQuery如何實現預先載入圖片功能的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn