前言 正所謂金三銀四五吃土,因此這些天幾個前端技術群討論最多的話題就是面試題了。某日群內討論一道面試題:“前端如何實現大量圖片預載入以及預載入進度動畫進度條顯示?” 恰巧本人以前jquery、zepto一把梭快樂切圖的時候,寫過不少形式的圖片預載入動畫。對於圖片預載入的原理稍微瞭解接觸過那麼一點點, ...
前言
正所謂金三銀四五吃土,因此這些天幾個前端技術群討論最多的話題就是面試題了。某日群內討論一道面試題:“前端如何實現大量圖片預載入以及預載入進度動畫進度條顯示?”
恰巧本人以前jquery、zepto一把梭快樂切圖的時候,寫過不少形式的圖片預載入動畫。對於圖片預載入的原理稍微瞭解接觸過那麼一點點,這裡獻醜一番簡單寫一個預載入案例,作為19年第一篇博(段)客(子)快樂一哈。
一、利用image對象搞事情
既然是利用image對象搞事情,那肯定少不了大量的img圖片。因此我從名字中包含刺激二字的網站上面扒了不少各位帶妹司機熱血沸騰的圖片,沒錯就是騰訊刺激戰場--各種武器圖片。
emmm,不皮了。我們直接進入主題內容,JavaScript當中的image對象。關於Image對象的介紹MDN上面寫的, 當new Image()
的時候會生成一個HTMLImageElement
.
HTMLImageElement
這是什麼?和我們熟悉的HTMLElement
這個節點有什麼不同呢?順著上面的鏈接提示,我們繼續順藤摸瓜,最後發現HTMLImageElement
屬於HTMLElement
孩子。
既然繼承了HTMLElement
特性,同理body元素有一個onload
屬性,那麼同理new Image得到對象也同樣擁有onload
屬性。
那麼就讓我們利用,new Image()
來搞事情
二、預載入和預載入動畫實現
1、批量設置圖片路徑
平常我們在接觸img
元素的時候,都知道書寫img
標簽的時候,必然少不了添加src
屬性,不然圖片載入不出來。所以我們第一步就是批量設置這些需要預載入的圖片路徑地址,這樣onload
才能發揮其作用。
這裡的圖片太多了,一張一張的手寫,未免太麻煩了。為了節省時間,這裡我拿出一年多以前剛剛學Node的時候寫的一個js腳本,來批量獲取圖片名稱生成數組對象列表。
PS:這裡就不掛載nodefs腳本代碼,文末我將會這個小demo地址附上(包括nodefs.js
),感興趣的小伙伴可以點擊訪問。
2、預載入圖片效果測試
因為我此前是用的webpack工具構建的項目,支持模塊引入imglist.js
. 這裡我為了demo演示,因此我們就直接將這個數組對象複製粘貼到演示HTML當中。
<body>
<h1 class="loading"></h1>
</body>
</html>
<script>
let imglist = [{name: 'AKM', url: 'AKM.png'},{name: 'AUG', url: 'AUG.png'},{name: 'AWM', url: 'AWM.png'},{name: 'crossbow', url: 'crossbow.png'},{name: 'Crowbar', url: 'Crowbar.png'},{name: 'DP-28', url: 'DP-28.png'},{name: 'G36C', url: 'G36C.png'},{name: 'Groza', url: 'Groza.png'},{name: 'Kar98k', url: 'Kar98k.png'},{name: 'M16A4', url: 'M16A4.png'},{name: 'M24', url: 'M24.png'},{name: 'M249', url: 'M249.png'},{name: 'M416', url: 'M416.png'},{name: 'M762', url: 'M762.png'},{name: 'Machete', url: 'Machete.png'},{name: 'Micro-UZI', url: 'Micro-UZI.png'},{name: 'Mini14', url: 'Mini14.png'},{name: 'Mk14', url: 'Mk14.png'},{name: 'MK47', url: 'MK47.png'},{name: 'P18C', url: 'P18C.png'},{name: 'p1911', url: 'p1911.png'},{name: 'P92', url: 'P92.png'},{name: 'Pan', url: 'Pan.png'},{name: 'QBU', url: 'QBU.png'},{name: 'QBZ', url: 'QBZ.png'},{name: 'R1895', url: 'R1895.png'},{name: 'R45', url: 'R45.png'},{name: 'S12K', url: 'S12K.png'},{name: 'S1897', url: 'S1897.png'},{name: 'S686', url: 'S686.png'},{name: 'Sawed-off', url: 'Sawed-off.png'},{name: 'SCAR-L', url: 'SCAR-L.png'},{name: 'Scorpion', url: 'Scorpion.png'},{name: 'Sickle', url: 'Sickle.png'},{name: 'Signal', url: 'Signal.png'},{name: 'SKS', url: 'SKS.png'},{name: 'SLR', url: 'SLR.png'},{name: 'Thomson', url: 'Thomson.png'},{name: 'UMP9', url: 'UMP9.png'},{name: 'Vector', url: 'Vector.png'},{name: 'VSS', url: 'VSS.png'},{name: 'win94', url: 'win94.png'}];
let length = imglist.length;
let images = new Array(); // 定義一個數組容器,用來存儲預載入完成的圖片
let loadEl = document.querySelector('.loading');
function preload () {
let count = 0; // 計算器,計算載入了多少圖片
for (let i = 0; i < length; i++) {
images[i] = new Image();
images[i].src = `./imgs/${imglist[i].url}`;
// 谷歌瀏覽器高版本支持大部分ES6,所以這裡就不用字元串拼接了。
images[i].onload = function () {
count++;
if (count === length) {
loadEl.innerHTML = '載入完成';
} else {
loadEl.innerHTML = '正在載入中';
}
}
}
}
preload();
</script>
打開頁面重新刷新一下,在控制台NetWork可以將圖片全部載入出來。emmm,但是由於本地載入速度太快了,一下子就載入完成。通過下麵截圖可以看到,載入時間不到1s就載入,並不能很好看的預載入過程。
3、預載入圖片真實環境模擬
所以為了小伙伴們能夠更加直觀的看到預載入的過程,這裡我們決定進行真實環境模擬:
①這裡我利用vscode自帶的插件,生成一個本地伺服器。
②然後在切換到瀏覽器控制臺下NetWork,將網速調整為Fast3G
③ 然後將之前載入中的代碼修改,成百分比顯示。
// loadEl.innerHTML = '正在載入中';
loadEl.innerHTML = `正在載入中${Math.round(count / length * 100)}%`;
最終效果如下:
三、小結
好了!以上就是鄙人對於前端圖片預載入一點簡單理解與複習了,主要回顧一些image()基本屬性點。
當然,前端圖片預載入方法也並不止這麼一種,方法還是有好幾種。所以後續使用何種方法就各位小伙伴自己了。這裡有一篇大佬翻譯的文章就提到三種前端預載入的方法,希望可以給大家一個參考。
這篇文章中的第二個方法,就是本文采用的方法。所以希望各位大佬待會點進看完之後,不要出來打我。畢竟我不是大佬代碼水平,我只是一個快樂前端段子手。
傳送門地址:譯:利用CSS、JavaScript及Ajax實現圖片預載入的三大方法
考慮新年第一篇文章,吹水過多不在狀態,所以良(很)心(皮)的我,決定錦上添花額外寫一個快樂loading動畫作為給我大哥賠罪。
快樂loading小動畫
這裡就是百分比數字,分割成兩位,然後通過數字的不同,改變圖片background-position
屬性,來完成loading預載入動畫。
images[i].onload = function () {
count++;
if (count === length) {
loadStart.style.display = 'none';
loadEnd.style.display = 'block';
loadEnd.onclick = function () {
alert('恭喜學習圖片預載入!');
}
} else {
// loadEl.innerHTML = '正在載入中';
// loadEl.innerHTML = `正在載入中${Math.round(count / length * 100)}%`;
let text = Math.round(count / length * 100);
let text1 = parseInt(text / 10);
let text2 = parseInt(text % 10);
console.log(text1, text2);
num1.style.backgroundPositionX = `${-47 + text1 * -60}px`
num2.style.backgroundPositionX = `${-47 + text2 * -60}px`
}
}
所以對完整blogDemo代碼感興趣的,可以從本人github上閱覽。
原創文章,文筆有限,才疏學淺,文中若有不正之處,再次再次再次歡迎各位啪啪的打臉賜教。(有句話說的好,重要的詞得說三遍。)
我是車大棒!我為我自己帶眼了!