預載入+監聽圖片資源載入製作進度條
這兩天遇到一個新需求:一個一鏡到底的h5動畫。因為功能的特殊性,就要求我們提前監聽頁面的靜態圖片是否全部載入完畢。即處理預載入。
總結下來,下次這種需求需要提前注意以下幾點:
一、圖片而不是背景圖
本來,我所用到的圖都是用背景圖製作的(因為非介面返回的圖片都要求用背景圖)。
但是監聽靜態圖片時,後來發現所用的方法監聽不到背景圖,所以改成了圖片。
這是一個坑。
二、獲取新載入的圖片:Img.load()
1、要監聽圖片我們要先獲取到頁面中的所有圖片:jq的方法:find()
var MyImg = $(body).find('img');
很簡單的解決了這個問題。
MyImg得到的是目標元素中的所有圖片的集合。
2、然後我們要遍歷所有的圖片,好判斷是否載入完畢:
依然是jq的方法:each()
MyImg.each(function(){ //在這裡實現 分別對每一個圖片的圖片載入結果 的監聽。 })
3、然後說如何監聽圖片載入:
萬年青jq方法:load()
Img.load(function(){ // 回撥裡,執行載入完畢一個的記錄處理 })
還好這次用的jq寫的程式碼,省了不少事。
為了記錄圖片載入完畢的個數,我在全域性設定一個變數:
var sum = 0;
並準備一個方法讓sum累加
function sumAdd(){ sum++; }
然後load方法的回撥裡,呼叫sumAdd
MyImg.load(()=>{ // 用於新載入的圖片 sumAdd(1); });
最後頁面載入完成後成功得到 sum=7;(本次案例頁面7張圖)
三、獲取快取的圖片:Img.complete
now
圖片載入是能控制了,但是為什麼我一重新整理他又監聽不到了?
哦!原來頁面載入完畢後重新整理,再展示的圖片都是快取的圖,而load又監聽不到快取的圖。
要了我的老命了。
於是我又找,什麼方法能監聽快取的圖啊?目標鎖定了js裡的img.complete。注意劃重點是js的屬性
if(MyImg[0].complete){ // 用於快取圖片 sumAdd(); }
有了之前準備的sumAdd函式做接應,快取圖片的個數也能計算出來了。
至此,一個非常簡易又簡陋的監聽就完成了。
題外話
之前不是這麼做的,而是load方法裡累加load的個數,complete裡累加快取的個數。
在電腦上測試,兩者河井互不犯,相安無事。
但是到手機上發現,會有6張快取圖1張載入圖,導致下邊要說的載入進度計算錯誤,先是變成70%,又變回20%。
後來才改成這兩種情況都累加到一處了。
四、預載入進度計算並展示
好了,現在需求升級。
為了友好的使用者體驗,你在後臺載入圖片的時候,使用者不能只看到一個載入中,等半天不知道到底有沒有反應。
所以我們要給使用者一個及時的反饋,就要獲取圖片載入的進度。
思路就是 :
載入進度 = 已載入圖片資源個數/總的圖片資源個數*100+'%';
有了公式,又有之前我們準備的sum(當前載入個數),這個載入進度輕而易舉就能得到了:
let progress = Math.ceil(sum/7*100);
7是當前頁面中圖片的總個數。而Math.ceil向上取整是為了在除不盡的時候不會出現小數點或99.9999%的情況。當然為了控制萬一超過100的情況,只需要保險設定一下:
progress>=100?100:progress
如果載入進度想做成進度條效果,只需要把得到的progress值賦給進度條的寬度即可。至於進度條怎麼做,看我這篇博文。css案例 - 評分效果的星星✨外衣
五、數字動畫效果:animate()
後來我又想,進度條旁邊加數字展示豈不是更好?
而作為一個有些許追求的程式設計師,我又不想直接做成數字是多少就生硬切換成多少的效果。
我想做逐漸變化的數字動畫效果
這就要另一個方法上場了。
對,沒錯,還是jq的方法 - animate()方法:
利用其step屬性達到動畫逐幀改變的效果,也就是文字從1累加漸變成100,而不是生硬的跳轉為100。
這個方法的用法是這樣的:
$('#loadingTxts').animate({count: progress},{ duration: 350, step: function() { if(isNaN(this.count)){ this.count = 0; return; } let boxText = Math.ceil(Number(this.count)); if(boxText >= 100){ boxText = 100; //接下來執行預載入完畢,頁面開始展示 ... } $('#loadingTxts').text(boxText+'%');// 文字展示 $('.progress').css('width',boxText+'%'); // 進度條寬度設定 } });
一個坑接一個坑,最後我們被折磨得沒了生氣的力氣。
大致參考程式碼:
$(function () { let nameLink = 'https://www.test.com/test/dist/images/', nameArr = ['1', '2', '3', '4', '5', '6', '7'], myImgs = $('.baby-box').find('img'), downAndCache = 0; function progressAni(i){ downAndCache += i; let progreVal = Math.ceil(downAndCache/nameArr.length*100); // 文字-單值變化動畫 $('#txtsBox').animate({ count: progreVal },{ duration: 350, step: function() { if(isNaN(this.count)){ this.count = 0; return; } let numberTxt = Math.ceil(Number(this.count)); if(numberTxt >= 100){ numberTxt = 100; $('.loading').fadeOut(); } $('#txtsBox').text(numberTxt+'%'); $('#progressBox').css('width',numberTxt+'%'); } }); } myImgs.each(function(a){ let Img = $(this); if(Img[0].complete){ // 用於快取圖片 progressAni(1); } Img.load(()=>{ // 用於新載入的圖片 progressAni(1); }); Img.error(function() { // 圖片載入失敗,可以選擇替換圖片 console.log(Img.attr('src')); Img.attr('src',nameLink + nameArr[a] + '.jpg'); }); }); });
2018-09-13 17:32:28