摘要:又譬如在一個多圖展示的網(wǎng)頁,由于圖片過多或圖片太大,我們希望圖片加載完再一次性顯示,而不是東一張西一張陸續(xù)顯示,這時候也需要用圖片一次性加載功能。
基于promise的圖片資源一次性加載或者預(yù)加載
作者:NEXT卓
場景描述不是每個網(wǎng)頁端的用戶都能用得起光纖,不是每張圖片都是壓縮得很小,有時候我們也想要看高清大圖,但是受限于網(wǎng)速有時候場景是這樣的:(很明顯左邊的第一張圖片還沒出來,其他的就出來了)
圖片資源預(yù)加載是一個很常見的需求,在網(wǎng)頁開發(fā)中,
譬如我們在開發(fā)一個基于canvas的游戲,涉及到圖片資源的時候,為了游戲的體驗,我們希望圖片資源全部加載才開始游戲。
又譬如在一個多圖展示的網(wǎng)頁,由于圖片過多或圖片太大,我們希望圖片加載完再一次性顯示,而不是東一張西一張陸續(xù)顯示,這時候也需要用圖片一次性加載功能。
圖片資源加載的原理在瀏覽器向服務(wù)器發(fā)送請求的過程中,如果圖片資源已經(jīng)加載過一次了,則不會再從服務(wù)器加載同一個圖片,
利用這個原理,我們的實現(xiàn)思路如下:
// 創(chuàng)建一個圖片對象 let img = new Image() img.src = "圖片地址" // 資源圖片加載完畢 img.onload = function() {}
基于這個原理我封裝了一個圖片資源加載的函數(shù),其結(jié)構(gòu)如下
/** * @description 圖片資源加載函數(shù) * 適用于canvas加載圖片,返回的是一個promise異步對象,response 的值為一個資源對象 * @param {Object} config 參數(shù)設(shè)置,是一個對象 * config.sourceData - 資源對象 {key: value} 資源名:資源地址 * config.mode - 默認(rèn)為false, 即使有失敗也會返回, mode為true,開啟嚴(yán)格模式,一個失敗則全部不返回 * config.target - 要預(yù)加載的目標(biāo)節(jié)點對象 * config.response - 默認(rèn)false, 是否返回promise異步對象,true為返回 * @return {null || Promise} */ const loadImg = (config) => { // 初始化設(shè)置參數(shù) let sourceData = config.sourceData let mode = config.mode || false let target = config.target || [] let needRes = config.response || false // 創(chuàng)建promise對象 let promise = new Promise((resolve, reject) => { // 函數(shù)內(nèi)部 // 完整代碼在最底層 }) }
下面讓我們先來看看這個函數(shù)的威力吧!
圖片加載函數(shù)描述與使用展示函數(shù)loadImg()用于圖片加載(函數(shù)實現(xiàn)代碼在最下面),接受的參數(shù)為一個設(shè)置對象config, 該對象有4個參數(shù)鍵值
config.sourceData: 必選參數(shù),資源對象 {key: value} 資源名:資源地址
config.target:可選參數(shù),要實現(xiàn)加載的目標(biāo)節(jié)點集
config.response:可選參數(shù),默認(rèn)false,不返回異步對象;設(shè)置為true,則返回,可通過then()進(jìn)行下一步數(shù)據(jù)操作
config.mode: 可選參數(shù),是否開啟嚴(yán)格模式
值為false(默認(rèn)值): 不開啟嚴(yán)格模式,該模式下如果有部分圖片加載失敗,其余圖片仍然顯示
值為true: 開啟嚴(yán)格模式,該模式下如果有部分圖片加載失敗,所有圖片都不顯示,如果需要返回結(jié)果,則返回結(jié)果是拋出一個錯誤
基本調(diào)用方式如下
// 圖片資源對象, 對象的key值是自定義的 // 到時候如果有返回,返回的response對象的key值跟這個一樣 let data = { img1: "http://plaechold.it/200x200", img2: "http://plaechold.it/200x200", img3: "http://plaechold.it/200x200" } // 需要預(yù)加載的節(jié)點集合 let images = document.querySelectorAll("img") // 開啟資源加載 loadImg({ sourceData: data, // 圖片資源對象 target: images, // 預(yù)加載目標(biāo) mode: true, // 是否開啟嚴(yán)格模式 response: false // 是否返回異步對象 })應(yīng)用實例
canvas中加載全部圖片再繪制到canvas面板中
記住必須設(shè)置config.response 的值為 true 才能用then進(jìn)行數(shù)據(jù)操作
let canvas = document.querySelector("canvas") let context = canvas.getContext("2d") // 圖片資源對象 let data = { bird: "http://plaechold.it/200x200", // 一只鳥的圖片 person: "http://plaechold.it/200x200", // 一個人類的圖片 tiger: "http://plaechold.it/200x200" // 一只老虎的圖片 } // 資源加載 loadImg({ sourceData: data, // 圖片資源對象 mode: true, // 是否開啟嚴(yán)格模式 response: true // 返回異步對象,然后可以使用then獲取結(jié)果進(jìn)行下一步處理 }) .then(res => { // res 也是一個對象{ bird: 圖片對象, person: 圖片對象, tiger: 圖片對象 } // 獲取所有的圖片對象 let images = Object.values(res) images.forEach((value, index) => { context.drawImage(value, index * 100, index * 100) }) }) // 記住必須設(shè)置config.response 的值為 true 才能用then進(jìn)行數(shù)據(jù)操作
html頁加載完畢一次性展示全部圖片實例
// 圖片資源對象 let data = { bird: "http://plaechold.it/200x200", // 一只鳥的圖片 person: "http://plaechold.it/200x200", // 一個人類的圖片 tiger: "http://plaechold.it/200x200" // 一只老虎的圖片 } let images = document.querySelectorAll("img") // 資源加載 loadImg({ sourceData: data, // 圖片資源對象 target: images, // 要渲染的節(jié)點集 mode: true, // 是否開啟嚴(yán)格模式 })
loadImg()如何在vue中優(yōu)雅地實現(xiàn)圖片加載
在vue中,由于vue是雙向數(shù)據(jù)綁定,因此我們可以先這樣:
假設(shè)我要加載的圖片html代碼如下
也就是說圖片的地址是動態(tài)的,綁定著imgSrc
整個實現(xiàn)代碼如下:
總結(jié)
基于這個函數(shù)的功能,我們可以做很多事情,除了上面的canvas繪圖和展示圖片外,還可以利用該
函數(shù)進(jìn)行預(yù)加載,譬如當(dāng)用戶在瀏覽第一頁的時候,我們可以先加載第二頁的圖片,具體的實現(xiàn)例子
這里就不多做展示了。簡單的如下
let nextImages = document.querySelectorAll(".next-img") // 下一頁的圖片節(jié)點 // 用戶只移動到按鈕上面還沒點擊 button.hover = function() { // 預(yù)加載圖片資源 loadImg({ sourceData: data, // 圖片資源對象 target: nextImages, // 要渲染的節(jié)點集 mode: true, // 是否開啟嚴(yán)格模式 }) } // 這樣當(dāng)用戶click點擊以后圖片資源已經(jīng)在hover的時候就加載了
完整的函數(shù)實現(xiàn)代碼如下
/** * @description 資源圖片加載函數(shù) * 適用于canvas加載圖片,返回的是一個promise異步對象,response 的值為一個資源對象 * @param {Object} config 參數(shù)設(shè)置,是一個對象 * config.sourceData - 資源對象 {key: value} 資源名:資源地址 * config.mode - 默認(rèn)為false, 即使有失敗也會返回, mode為true,開啟嚴(yán)格模式,一個失敗則全部不返回 * config.target - 要預(yù)加載的目標(biāo)節(jié)點對象 * config.response - 默認(rèn)false, 是否返回promise異步對象,true為返回 * @return {null || Promise} */ const loadImg = (config) => { // 初始化設(shè)置參數(shù) let sourceData = config.sourceData let mode = config.mode || false let target = config.target || [] let needRes = config.response || false // 創(chuàng)建promise對象 let promise = new Promise((resolve, reject) => { // 資源加載進(jìn)度 let loadNum = 0 // 資源加載的結(jié)果集 let response = {} // 如果是非嚴(yán)格模式 if (mode === false) { // 遍歷加載每個資源 Object.keys(sourceData).forEach(key => { let source = new Image() // 失敗或者成功都寫入response source.onload = source.onerror = () => { response[key] = source loadNum++ if (loadNum === Object.keys(sourceData).length) { // 如果有目標(biāo)對象 if (target) { target.forEach((item, index) => { item.src = Object.values(sourceData)[index] }) } // 成功 resolve(response) } } // src的賦值放在onload和onerror事件后面,這樣才能兼容IE source.src = sourceData[key] }) } else if (mode === true) { // 嚴(yán)格模式:一個失敗直接結(jié)束且返回空對象 // 遍歷加載每個資源 Object.keys(sourceData).forEach(key => { let source = new Image() // 成功則寫入response source.onload = () => { response[key] = source loadNum++ if (loadNum === Object.keys(sourceData).length) { // 如果有目標(biāo)對象 if (target) { target.forEach((item, index) => { item.src = Object.values(sourceData)[index] }) } resolve(response) } } // 失敗則返回空 source.onerror = () => { // 失敗 reject(new Error()) } // src的賦值必須放在最后,兼容IE source.src = sourceData[key] }) } }) // 結(jié)束 if (needRes) { return promise } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/54496.html
摘要:又譬如在一個多圖展示的網(wǎng)頁,由于圖片過多或圖片太大,我們希望圖片加載完再一次性顯示,而不是東一張西一張陸續(xù)顯示,這時候也需要用圖片一次性加載功能。 基于promise的圖片資源一次性加載或者預(yù)加載 作者:NEXT卓 場景描述 不是每個網(wǎng)頁端的用戶都能用得起光纖,不是每張圖片都是壓縮得很小,有時候我們也想要看高清大圖,但是受限于網(wǎng)速有時候場景是這樣的:(很明顯左邊的第一張圖片還沒出來,其...
摘要:什么是是的一種使用模式,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問的問題。由于同源策略,一般來說位于的網(wǎng)頁無法與不是的服務(wù)器溝通,而的元素是一個例外。利用元素的這個開放策略,網(wǎng)頁可以得到從其他來源動態(tài)產(chǎn)生的資料,而這種使用模式就是所謂的。 什么是jsonp JSONP(JSON with Padding)是JSON的一種使用模式,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問的問題。由于同源策略,一般來說...
閱讀 3454·2021-11-22 12:00
閱讀 671·2019-08-29 13:24
閱讀 2905·2019-08-29 11:31
閱讀 2586·2019-08-26 14:00
閱讀 3185·2019-08-26 11:42
閱讀 2476·2019-08-23 18:31
閱讀 797·2019-08-23 18:27
閱讀 2844·2019-08-23 16:58