摘要:又譬如在一個(gè)多圖展示的網(wǎng)頁(yè),由于圖片過(guò)多或圖片太大,我們希望圖片加載完再一次性顯示,而不是東一張西一張陸續(xù)顯示,這時(shí)候也需要用圖片一次性加載功能。
基于promise的圖片資源一次性加載或者預(yù)加載
作者:NEXT卓
場(chǎng)景描述不是每個(gè)網(wǎng)頁(yè)端的用戶(hù)都能用得起光纖,不是每張圖片都是壓縮得很小,有時(shí)候我們也想要看高清大圖,但是受限于網(wǎng)速有時(shí)候場(chǎng)景是這樣的:(很明顯左邊的第一張圖片還沒(méi)出來(lái),其他的就出來(lái)了)
圖片資源預(yù)加載是一個(gè)很常見(jiàn)的需求,在網(wǎng)頁(yè)開(kāi)發(fā)中,
譬如我們?cè)陂_(kāi)發(fā)一個(gè)基于canvas的游戲,涉及到圖片資源的時(shí)候,為了游戲的體驗(yàn),我們希望圖片資源全部加載才開(kāi)始游戲。
又譬如在一個(gè)多圖展示的網(wǎng)頁(yè),由于圖片過(guò)多或圖片太大,我們希望圖片加載完再一次性顯示,而不是東一張西一張陸續(xù)顯示,這時(shí)候也需要用圖片一次性加載功能。
圖片資源加載的原理在瀏覽器向服務(wù)器發(fā)送請(qǐng)求的過(guò)程中,如果圖片資源已經(jīng)加載過(guò)一次了,則不會(huì)再?gòu)姆?wù)器加載同一個(gè)圖片,
利用這個(gè)原理,我們的實(shí)現(xiàn)思路如下:
// 創(chuàng)建一個(gè)圖片對(duì)象 let img = new Image() img.src = "圖片地址" // 資源圖片加載完畢 img.onload = function() {}
基于這個(gè)原理我封裝了一個(gè)圖片資源加載的函數(shù),其結(jié)構(gòu)如下
/** * @description 圖片資源加載函數(shù) * 適用于canvas加載圖片,返回的是一個(gè)promise異步對(duì)象,response 的值為一個(gè)資源對(duì)象 * @param {Object} config 參數(shù)設(shè)置,是一個(gè)對(duì)象 * config.sourceData - 資源對(duì)象 {key: value} 資源名:資源地址 * config.mode - 默認(rèn)為false, 即使有失敗也會(huì)返回, mode為true,開(kāi)啟嚴(yán)格模式,一個(gè)失敗則全部不返回 * config.target - 要預(yù)加載的目標(biāo)節(jié)點(diǎn)對(duì)象 * config.response - 默認(rèn)false, 是否返回promise異步對(duì)象,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對(duì)象 let promise = new Promise((resolve, reject) => { // 函數(shù)內(nèi)部 // 完整代碼在最底層 }) }
下面讓我們先來(lái)看看這個(gè)函數(shù)的威力吧!
圖片加載函數(shù)描述與使用展示函數(shù)loadImg()用于圖片加載(函數(shù)實(shí)現(xiàn)代碼在最下面),接受的參數(shù)為一個(gè)設(shè)置對(duì)象config, 該對(duì)象有4個(gè)參數(shù)鍵值
config.sourceData: 必選參數(shù),資源對(duì)象 {key: value} 資源名:資源地址
config.target:可選參數(shù),要實(shí)現(xiàn)加載的目標(biāo)節(jié)點(diǎn)集
config.response:可選參數(shù),默認(rèn)false,不返回異步對(duì)象;設(shè)置為true,則返回,可通過(guò)then()進(jìn)行下一步數(shù)據(jù)操作
config.mode: 可選參數(shù),是否開(kāi)啟嚴(yán)格模式
值為false(默認(rèn)值): 不開(kāi)啟嚴(yán)格模式,該模式下如果有部分圖片加載失敗,其余圖片仍然顯示
值為true: 開(kāi)啟嚴(yán)格模式,該模式下如果有部分圖片加載失敗,所有圖片都不顯示,如果需要返回結(jié)果,則返回結(jié)果是拋出一個(gè)錯(cuò)誤
基本調(diào)用方式如下
// 圖片資源對(duì)象, 對(duì)象的key值是自定義的 // 到時(shí)候如果有返回,返回的response對(duì)象的key值跟這個(gè)一樣 let data = { img1: "http://plaechold.it/200x200", img2: "http://plaechold.it/200x200", img3: "http://plaechold.it/200x200" } // 需要預(yù)加載的節(jié)點(diǎn)集合 let images = document.querySelectorAll("img") // 開(kāi)啟資源加載 loadImg({ sourceData: data, // 圖片資源對(duì)象 target: images, // 預(yù)加載目標(biāo) mode: true, // 是否開(kāi)啟嚴(yán)格模式 response: false // 是否返回異步對(duì)象 })應(yīng)用實(shí)例
canvas中加載全部圖片再繪制到canvas面板中
記住必須設(shè)置config.response 的值為 true 才能用then進(jìn)行數(shù)據(jù)操作
let canvas = document.querySelector("canvas") let context = canvas.getContext("2d") // 圖片資源對(duì)象 let data = { bird: "http://plaechold.it/200x200", // 一只鳥(niǎo)的圖片 person: "http://plaechold.it/200x200", // 一個(gè)人類(lèi)的圖片 tiger: "http://plaechold.it/200x200" // 一只老虎的圖片 } // 資源加載 loadImg({ sourceData: data, // 圖片資源對(duì)象 mode: true, // 是否開(kāi)啟嚴(yán)格模式 response: true // 返回異步對(duì)象,然后可以使用then獲取結(jié)果進(jìn)行下一步處理 }) .then(res => { // res 也是一個(gè)對(duì)象{ bird: 圖片對(duì)象, person: 圖片對(duì)象, tiger: 圖片對(duì)象 } // 獲取所有的圖片對(duì)象 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頁(yè)加載完畢一次性展示全部圖片實(shí)例
// 圖片資源對(duì)象 let data = { bird: "http://plaechold.it/200x200", // 一只鳥(niǎo)的圖片 person: "http://plaechold.it/200x200", // 一個(gè)人類(lèi)的圖片 tiger: "http://plaechold.it/200x200" // 一只老虎的圖片 } let images = document.querySelectorAll("img") // 資源加載 loadImg({ sourceData: data, // 圖片資源對(duì)象 target: images, // 要渲染的節(jié)點(diǎn)集 mode: true, // 是否開(kāi)啟嚴(yán)格模式 })
loadImg()如何在vue中優(yōu)雅地實(shí)現(xiàn)圖片加載
在vue中,由于vue是雙向數(shù)據(jù)綁定,因此我們可以先這樣:
假設(shè)我要加載的圖片html代碼如下
也就是說(shuō)圖片的地址是動(dòng)態(tài)的,綁定著imgSrc
整個(gè)實(shí)現(xiàn)代碼如下:
總結(jié)
基于這個(gè)函數(shù)的功能,我們可以做很多事情,除了上面的canvas繪圖和展示圖片外,還可以利用該
函數(shù)進(jìn)行預(yù)加載,譬如當(dāng)用戶(hù)在瀏覽第一頁(yè)的時(shí)候,我們可以先加載第二頁(yè)的圖片,具體的實(shí)現(xiàn)例子
這里就不多做展示了。簡(jiǎn)單的如下
let nextImages = document.querySelectorAll(".next-img") // 下一頁(yè)的圖片節(jié)點(diǎn) // 用戶(hù)只移動(dòng)到按鈕上面還沒(méi)點(diǎn)擊 button.hover = function() { // 預(yù)加載圖片資源 loadImg({ sourceData: data, // 圖片資源對(duì)象 target: nextImages, // 要渲染的節(jié)點(diǎn)集 mode: true, // 是否開(kāi)啟嚴(yán)格模式 }) } // 這樣當(dāng)用戶(hù)click點(diǎn)擊以后圖片資源已經(jīng)在hover的時(shí)候就加載了
完整的函數(shù)實(shí)現(xiàn)代碼如下
/** * @description 資源圖片加載函數(shù) * 適用于canvas加載圖片,返回的是一個(gè)promise異步對(duì)象,response 的值為一個(gè)資源對(duì)象 * @param {Object} config 參數(shù)設(shè)置,是一個(gè)對(duì)象 * config.sourceData - 資源對(duì)象 {key: value} 資源名:資源地址 * config.mode - 默認(rèn)為false, 即使有失敗也會(huì)返回, mode為true,開(kāi)啟嚴(yán)格模式,一個(gè)失敗則全部不返回 * config.target - 要預(yù)加載的目標(biāo)節(jié)點(diǎn)對(duì)象 * config.response - 默認(rèn)false, 是否返回promise異步對(duì)象,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對(duì)象 let promise = new Promise((resolve, reject) => { // 資源加載進(jìn)度 let loadNum = 0 // 資源加載的結(jié)果集 let response = {} // 如果是非嚴(yán)格模式 if (mode === false) { // 遍歷加載每個(gè)資源 Object.keys(sourceData).forEach(key => { let source = new Image() // 失敗或者成功都寫(xiě)入response source.onload = source.onerror = () => { response[key] = source loadNum++ if (loadNum === Object.keys(sourceData).length) { // 如果有目標(biāo)對(duì)象 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)格模式:一個(gè)失敗直接結(jié)束且返回空對(duì)象 // 遍歷加載每個(gè)資源 Object.keys(sourceData).forEach(key => { let source = new Image() // 成功則寫(xiě)入response source.onload = () => { response[key] = source loadNum++ if (loadNum === Object.keys(sourceData).length) { // 如果有目標(biāo)對(duì)象 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)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/92130.html
摘要:又譬如在一個(gè)多圖展示的網(wǎng)頁(yè),由于圖片過(guò)多或圖片太大,我們希望圖片加載完再一次性顯示,而不是東一張西一張陸續(xù)顯示,這時(shí)候也需要用圖片一次性加載功能。 基于promise的圖片資源一次性加載或者預(yù)加載 作者:NEXT卓 場(chǎng)景描述 不是每個(gè)網(wǎng)頁(yè)端的用戶(hù)都能用得起光纖,不是每張圖片都是壓縮得很小,有時(shí)候我們也想要看高清大圖,但是受限于網(wǎng)速有時(shí)候場(chǎng)景是這樣的:(很明顯左邊的第一張圖片還沒(méi)出來(lái),其...
摘要:目前,常用的模塊規(guī)范主要有兩種和。攔截全局請(qǐng)求一直接引入腳本攔截需要的回調(diào)或函數(shù)。深刻知道一個(gè)良好的命名規(guī)范的重要性,同時(shí)在項(xiàng)目中也會(huì)遇到一些命名的瓶頸。 基于 Three.js 的超快的 3D 開(kāi)發(fā)框架:Whitestorm.js Whitestorm.js 是一款基于 Three.js 超快的 Web 應(yīng)用 3D 開(kāi)發(fā)框架。它為普通的 Three.js 任務(wù)提供封裝、使搭建環(huán)境、...
摘要:什么是是的一種使用模式,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問(wèn)的問(wèn)題。由于同源策略,一般來(lái)說(shuō)位于的網(wǎng)頁(yè)無(wú)法與不是的服務(wù)器溝通,而的元素是一個(gè)例外。利用元素的這個(gè)開(kāi)放策略,網(wǎng)頁(yè)可以得到從其他來(lái)源動(dòng)態(tài)產(chǎn)生的資料,而這種使用模式就是所謂的。 什么是jsonp JSONP(JSON with Padding)是JSON的一種使用模式,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問(wèn)的問(wèn)題。由于同源策略,一般來(lái)說(shuō)...
閱讀 1796·2023-04-25 22:42
閱讀 2220·2021-09-22 15:16
閱讀 3496·2021-08-30 09:44
閱讀 495·2019-08-29 16:44
閱讀 3317·2019-08-29 16:20
閱讀 2524·2019-08-29 16:12
閱讀 3397·2019-08-29 16:07
閱讀 676·2019-08-29 15:08