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