天天看點

javascript圖檔預加載技術(詳細示範)

本文所提到的預加載技術主要是讓javascript快速擷取圖檔頭部資料的尺寸。

一段典型的使用預加載擷取圖檔大小的例子: 

複制代碼代碼如下:

var imgLoad = function (url, callback) { 

var img = new Image(); 

img.src = url; 

if (img.complete) { 

callback(img.width, img.height); 

} else { 

img.onload = function () { 

callback(img.width, img.height); 

img.onload = null; 

}; 

}; 

}; 

可以看到使用onload的方式必須等待圖檔加載完畢,其速度不敢恭維。 

web應用程式差別于桌面應用程式,響應速度才是最好的使用者體驗。如果想要速度與優雅兼得,那就必須提前獲得圖檔尺寸,如何在圖檔沒有加載完畢就能擷取圖檔尺寸? 

十多年的上網經驗告訴我:浏覽器在加載圖檔的時候你會看到圖檔會先占用一塊地然後才慢慢加載完畢,并且這裡大部分的圖檔都是沒有預設width與height屬性的,因為浏覽器能夠擷取圖檔的頭部資料。基于此,隻需要使用javascript定時偵測圖檔的尺寸狀态便可得知圖檔尺寸就緒的狀态。 

實作代碼(2011-03-11更新): 

2011-03-12 更新: 

隻使用一定時器,優化性能 

複制代碼代碼如下:

// 圖檔頭資料加載就緒事件 

// @param {String} 圖檔路徑 

// @param {Function} 擷取尺寸的回調函數 (參數1接收width;參數2接收height) 

// @param {Function} 加載錯誤的回調函數 (可選) 

(function () { 

var list = [], intervalId = null, 

tick = function () { 

var i = 0; 

for (; i < list.length; i++) { 

list[i].end ? list.splice(i--, 1) : list[i](); 

}; 

!list.length && stop(); 

}, 

stop = function () { 

clearInterval(intervalId); 

intervalId = null; 

}; 

this.imgReady = function (url, callback, error) { 

var check, end, width, height, offsetWidth, offsetHeight, div, 

accuracy = 1024, 

doc = document, 

container = doc.body || doc.getElementsByTagName('head')[0], 

img = new Image(); 

img.src = url; 

if (!callback) return img; 

// 如果圖檔被緩存,則直接傳回緩存資料 

if (img.complete) return callback(img.width, img.height); 

// 向頁面插入隐秘圖像,用來監聽圖檔是否占位 

div = doc.createElement('div'); 

div.style.cssText = 'visibility:hidden;position:absolute;left:0;top:0;width:1px;height:1px;overflow:hidden'; 

div.appendChild(img) 

container.appendChild(div); 

width = img.offsetWidth; 

height = img.offsetHeight; 

// 完全加載完畢的事件 

img.onload = function () { 

end(); 

callback(img.width, img.height); 

}; 

// 加載錯誤後的事件 

img.onerror = function () { 

end(); 

error && error(); 

}; 

// 檢測圖檔是否已經占位 

check = function () { 

offsetWidth = img.offsetWidth; 

offsetHeight = img.offsetHeight; 

if (offsetWidth !== width || offsetHeight !== height || offsetWidth * offsetHeight > accuracy) { 

end(); 

callback(offsetWidth, offsetHeight); 

}; 

}; 

check.url = url; 

// 操作結束後進行清理 

// 删除元素與事件,避免IE記憶體洩漏 

end = function () { 

check.end = true; 

img.onload = img.onerror = null; 

div.innerHTML = ''; 

div.parentNode.removeChild(div); 

}; 

// 将檢測圖檔是否占位的函數加入定時器列隊定期執行 

// 同一圖檔隻加入一個檢測器 

// 無論何時隻允許出現一個定時器,減少浏覽器性能損耗 

!check.end && check(); 

for (var i = 0; i < list.length; i ++) { 

if (list[i].url === url) return; 

}; 

if (!check.end) { 

list.push(check); 

if (!intervalId) intervalId = setInterval(tick, 150); 

}; 

}; 

})(); 

是不是很簡單?這樣的方式擷取攝影級别照片尺寸的速度往往是onload方式的幾十多倍,而對于web普通(800×600内)浏覽級别的圖檔能達到秒殺效果。

源引:http://www.jb51.net/article/26531.htm

繼續閱讀