摘要:本文同步自我得博客最近要用做一個(gè)動(dòng)畫功能,為了確保動(dòng)畫在播放的時(shí)候能夠順利和平滑,我需要對(duì)所用到的圖片素材進(jìn)行預(yù)加載,下面跟大家分享一下我實(shí)現(xiàn)這個(gè)功能的過程單圖片預(yù)加載目前最常見的一種實(shí)現(xiàn)方式如下接下來(lái)可以使用圖片了接下來(lái)可以使用圖片了首先
本文同步自我得博客:http://www.joeray61.com
最近要用javascript做一個(gè)動(dòng)畫功能,為了確保動(dòng)畫在播放的時(shí)候能夠順利和平滑,我需要對(duì)所用到的圖片素材進(jìn)行預(yù)加載,下面跟大家分享一下我實(shí)現(xiàn)這個(gè)功能的過程
單圖片預(yù)加載目前最常見的一種實(shí)現(xiàn)方式如下
function preloadImg(url) { var img = new Image(); img.src = url; if(img.complete) { //接下來(lái)可以使用圖片了 //do something here } else { img.onload = function() { //接下來(lái)可以使用圖片了 //do something here }; } }
首先實(shí)例化一個(gè)Image對(duì)象賦值給img,然后設(shè)置img.src為參數(shù)url指定的圖片地址,接著判斷img的complete屬性,如果本地有這張圖片的緩存,則該值為true,此時(shí)我們可以直接操作這張圖片,如果本地沒有緩存,則該值為false,此時(shí)我們需要監(jiān)聽img的onload事件,把對(duì)img的操作放在onload的回調(diào)函數(shù)里面,經(jīng)過測(cè)試,這種方案基本能夠兼容目前所有瀏覽器
多圖片預(yù)加載很多場(chǎng)景下,單圖片預(yù)加載并不能滿足我們的需求,因?yàn)橄駝?dòng)畫這種功能通常都會(huì)有很多的圖片素材,接下來(lái)我們就在原來(lái)單圖片預(yù)加載的基礎(chǔ)上來(lái)改進(jìn)我們的函數(shù)
function preloadImg(list) { var imgs = arguments[1] || [], //用于存儲(chǔ)預(yù)加載好的圖片資源 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 = [......], //此處省略一萬(wàn)個(gè)字符 imgs = preloadImg();
因?yàn)閹瑒?dòng)畫可能需要保證每一幀動(dòng)畫所用的圖片的順序,所以我在這段代碼中使用遞歸的方式,在上一張加載完成之后再去加載下一張圖片,每加載一張圖片,就把這張圖片資源存儲(chǔ)到imgs數(shù)組中,并且把這張圖片的地址從地址數(shù)組list中去掉,當(dāng)list中已經(jīng)沒有地址的時(shí)候跳出遞歸,并返回imgs數(shù)組
設(shè)想很美好,現(xiàn)實(shí)很殘酷,這段代碼有2個(gè)不能忍受的問題
首先,我很有可能拿不到最后返回的imgs數(shù)組,因?yàn)橹灰袌D片在本地沒有緩存,imgs的存儲(chǔ)操作都會(huì)放到onload的回調(diào)事件中,而事件監(jiān)聽也屬于javascript中異步操作的一種,在綁定完onload事件的回調(diào)函數(shù)后,preloadImg函數(shù)就執(zhí)行結(jié)束了,沒有任何返回值,外部imgs變量接收到的值為undefined,只有在所有圖片都有本地緩存的情況下,外部imgs變量才能順利拿到存儲(chǔ)了全部預(yù)加載圖片資源的數(shù)組
在加載完一張圖片之后才去加載下一張,整個(gè)預(yù)加載圖片的過程所需要的時(shí)間相對(duì)會(huì)比較長(zhǎng),用戶體驗(yàn)會(huì)降低,而且本來(lái)異步操作具體速度快的特性,這樣的實(shí)現(xiàn)方式等于完全棄置了onload異步的這個(gè)特性
多圖片預(yù)加載(改進(jìn)版)這次我們直接把一個(gè)空數(shù)組作為參數(shù)傳進(jìn)函數(shù),圖片全部存儲(chǔ)到這個(gè)數(shù)組里面,下面是改進(jìn)后的函數(shù)代碼(假設(shè)我們可以使用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 = [......], //此處省略一萬(wàn)個(gè)字符 imgs = []; $.when(preloadImg(list, imgs)).done( function() { //預(yù)加載結(jié)束 //do something here } );
在分別給每一個(gè)img綁定onload的回調(diào)函數(shù)時(shí)采用了閉包的方式,目的是為了保存住當(dāng)前的遞增變量i,要是不這么做,結(jié)果將會(huì)是list地址中沒有本地緩存的圖片都存儲(chǔ)到imgs的最后一個(gè)元素上
這次每載入一張圖片,我們并沒有把這張圖片的地址從list數(shù)組中去掉,這樣后續(xù)需要使用list數(shù)組的數(shù)據(jù)時(shí)就能夠順利獲取到
在這次的代碼中,我們引入了jQuery的Deferred對(duì)象,這樣更方便我把握整個(gè)預(yù)加載圖片的過程,Deferred對(duì)象或者Promise對(duì)象的實(shí)現(xiàn)原理可以參看我的這篇文章
thx for reading, hope u enjoy
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/85310.html
摘要:圖片的預(yù)加載是提升用戶體驗(yàn)而損失性能的一種做法,而懶加載的性能就比較好了,所以將兩個(gè)結(jié)合起來(lái)放到程序中是一種不錯(cuò)的選擇。 最近在做H5滑頁(yè)時(shí),遇到一些比較大的場(chǎng)景,動(dòng)輒二十、三十頁(yè),而圖片更是可恨的能達(dá)到上百個(gè),所以就會(huì)導(dǎo)致場(chǎng)景在加載的時(shí)候遇到網(wǎng)速比較慢的時(shí)候,用戶等待的時(shí)間特別長(zhǎng),這樣的話,就有可能導(dǎo)致一部分的用戶沒有耐心,而丟失這部分用戶,于是就有了這里的圖片的預(yù)加載和懶加載,記個(gè)...
摘要:但這些加載器對(duì)于瀏覽器的加載優(yōu)先級(jí)隊(duì)列完全束手無(wú)策,這也使得他們不得不屈服于同樣的性能問題。 參考文章:https://developer.mozilla.org... 先簡(jiǎn)單介紹下 link 標(biāo)簽作用 你可以在頁(yè)面 元素內(nèi)部使用 標(biāo)簽書寫一些聲明式的資源獲取請(qǐng)求 preload (預(yù)加載) 有些資源是在頁(yè)面加載完成后即刻需要的,對(duì)于這種即刻需要的資源,你可能希望在頁(yè)面加載的生命...
摘要:對(duì)象是無(wú)法通過這種方式深拷貝。這就是函數(shù)防抖和節(jié)流要做的事情。函數(shù)防抖當(dāng)觸發(fā)頻率過高時(shí)函數(shù)基本停止執(zhí)行而函數(shù)節(jié)流則是按照一定的頻率執(zhí)行事件。 對(duì)象的深淺拷貝 對(duì)象的深拷貝與淺拷貝的區(qū)別: 淺拷貝:僅僅復(fù)制對(duì)象的引用, 而不是對(duì)象本身。 深拷貝:把復(fù)制的對(duì)象所引用的全部對(duì)象都復(fù)制一遍 淺拷貝的實(shí)現(xiàn): var obj = { age : 18, person : { ...
摘要:虛擬代理在開發(fā)中,我們往往將這個(gè)對(duì)象的實(shí)例化操作,放到函數(shù)內(nèi)部執(zhí)行,這樣的操作會(huì)減少不必要的實(shí)例化對(duì)象的開銷,造成資源的浪費(fèi)。這種使用的情況我們將之成為虛擬代理。但是在中我們使用最多,也最常見的就是虛擬代理和緩存代理。 所謂的的代理模式就是為一個(gè)對(duì)象找一個(gè)替代對(duì)象,以便對(duì)原對(duì)象進(jìn)行訪問。 使用代理的原因是我們不愿意或者不想對(duì)原對(duì)象進(jìn)行直接操作,我們使用代理就是讓它幫原對(duì)象進(jìn)行一系列的操...
閱讀 1265·2021-09-27 13:35
閱讀 2563·2021-09-06 15:12
閱讀 3380·2019-08-30 15:55
閱讀 2829·2019-08-30 15:43
閱讀 432·2019-08-29 16:42
閱讀 3446·2019-08-29 15:39
閱讀 3062·2019-08-29 12:28
閱讀 1239·2019-08-29 11:11