js圖片預載入詳解

antzone發表於2017-04-06

圖片預載入技術在當前的應用非常的廣泛,比如在滑鼠懸浮圖片實現翻轉效果中,如果圖片還沒有載入完成,那麼此效果的人性化程度就會大打折扣,甚至會給網站減分。如果將需要的圖片事先下載到本地,那麼就可以讓效果流暢的進行。這就是所謂的圖片預載入,下面詳細介紹一下它的實現過程。下面先看一個基本的圖片預載入程式碼:

[JavaScript] 純文字檢視 複製程式碼
function preloadimages(arr){
  var newimages=[]
  var arr=(typeof arr!="object")? [arr] : arr;//確保引數總是陣列
  for (var index=0; index<arr.length; index++){
    newimages[index]=new Image()
    newimages[index].src=arr[index]
  }
}

上面的程式碼實現了最基本的圖片預載入效果,簡單對大媽做一下說明:

(1).preloadimages(arr),引數是存放圖片地址的陣列,也可以是單個地址(當然這時候不是陣列)。

(2).var newimages=[],宣告一個陣列用來儲存圖片地址。

(3).var arr=(typeof arr!="object")? [arr] : arr,判斷是不是一個陣列,不是那麼就人為的包裝成一個陣列,否則直接返回陣列。

(4).for (var index=0; index<arr.length; index++){},使用for迴圈遍歷陣列中的每一個元素,也就是圖片地址。

(5).newimages[index]=new Image(),建立一個Image物件。

(6).newimages[index].src=arr[index],設定對應圖片物件的src屬性,也就是是圖片的地址。

簡單的使用程式碼:

[JavaScript] 純文字檢視 複製程式碼
preloadimages(['one.gif', 'two.gif', 'three.gif'])

上面只是最基本的圖片預載入,但是它往往在實際應用中有所欠缺,通常我們需要確切的知道圖片什麼時候載入完畢,然後再去幹一些需要的事情,可以通過onload事件實現,程式碼修改如下:

[JavaScript] 純文字檢視 複製程式碼
function preloadimages(arr){
  var newimages=[], loadedimages=0
  var arr=(typeof arr!="object")? [arr] : arr
  function imageloadpost(){
    loadedimages++
    if (loadedimages==arr.length){
      alert("圖片已經載入完成")
    }
  }
  for (var index=0; index<arr.length; index++){
    newimages[index]=new Image()
    newimages[index].src=arr[index]
    newimages[index].onload=function(){
      imageloadpost()
    }
    newimages[index].onerror=function(){
      imageloadpost()
    }
  }
}

上面的程式碼中,當圖片全部載入完成(成功或失敗)後,瀏覽器將會彈出“圖片已經載入完成”的訊息。

現在,將為preloadimages()函式增加一個回撥函式來處理後續的操作,通常會為我們的preloadimages()函式增加一個匿名函式做為引數,來完成我們需要的功能。如此之後,我們呼叫preloadimages()函式的程式碼可能會如下面這樣。

[JavaScript] 純文字檢視 複製程式碼
preloadimages(imagesarray, function(){
  //圖片載入完成之後執行的操作
})

下面來做一點改變,讓程式碼看起來更直觀,更易於理解,改造完成之後,preloadimages()函式的呼叫看起來如下所示。

[JavaScript] 純文字檢視 複製程式碼
preloadimages(imagesarray).done(function(){
 //圖片載入完成後的操作
})

上面這種寫法大家一看一定都會覺得非常清晰明瞭,那麼接下來,繼續來改造我們的preloadimages()函式。

[JavaScript] 純文字檢視 複製程式碼
function preloadimages(arr){   
  var newimages=[], loadedimages=0
  var postaction=function(){}  //此處增加了一個postaction函式
  var arr=(typeof arr!="object")? [arr] : arr
  function imageloadpost(){
    loadedimages++
    if (loadedimages==arr.length){
      postaction(newimages) //載入完成用我們呼叫postaction函式並將newimages陣列做為引數傳遞進去
    }
  }
  for (var index=0; index<arr.length; index++){
    newimages[index]=new Image()
    newimages[index].src=arr[index]
    newimages[index].onload=function(){
      imageloadpost()
    }
    newimages[index].onerror=function(){
      imageloadpost()
    }
  }
  return { //此處返回一個空白物件的done方法
    done:function(f){
      postaction=f || postaction
    }
  }
}

上面的程式碼稍作修改了幾個地方: 

首先,增加了一個postaction函式,該函式被用來做為圖片載入完成後的回撥函式,使用者可以在後面呼叫的時候用自己的處理函式覆蓋掉該函式。

第二,preloadimages()函式返回了一個空物件,其中包含一個簡單的done()方法,這是實現本次改造的關鍵所在,確保了鏈式呼叫的實現。

最後,呼叫變為如下形式:

[JavaScript] 純文字檢視 複製程式碼
preloadimages(['1.gif', '2.gif', '3.gif']).done(function(images){
  alert(images.length) //alerts 3
  alert(images[0].src+" "+images[0].width) //alerts '1.gif 220'
})

相關文章