實戰解決小程式圖片載入問題
相較於web端或者H5開發,小程式本身在效能上弱很多(但使用者體驗上要好)。以前開發時伺服器效能過剩在那裡幫你撐著臉面,你對自己的程式碼質量和程式設計習慣心裡沒數,小程式就是一面鏡子。
廢話少說,要解決的問題是,小程式載入圖片閃爍,漸漸出現,出現的很慢等等效果不盡人意的體驗。
如果你的小程式本身只用載入很少的圖片,那麼其實問題不大。如果是像購物APP那樣或者是一款有圖片列表的應用,那麼以下方案肯定能幫到你。
1.從源頭把控,所有的圖片放到雲端儲存上(或者用小程式開發工具的素材管理),後臺對圖片進行可接受範圍內的最大限度壓縮,圖片寬高不用太大,大概預留你圖片容器的1.5倍就行了,除非你做圖片放大鏡功能,否則小程式上載入2倍圖意義不大,反正圖片也不可以被長按,被放大。
2.官方文件上寫著圖片image
上自帶lazy-load
(懶載入),預設是關閉的,你把它開啟,但是要記得它只在兩個固定容器(page
或scroll-view
)下才有用。
以上方案針對下滑載入更多列表的應用,類似下圖這個,是有一定效果的:
3.做完上述兩步,如果你發現就算你一屏就載入4張圖片,每張才30k以內還是一張一張的閃現,尤其在安卓上(嘿嘿,你以為安卓會一直輸下去?),但是下滑載入更多時下面的圖片顯示體驗卻意外順滑(官方的lazy-load生效了),那麼就繼續看。
就算首屏就載入四張小圖,圖片還沒有全都刷的一下出來那種順暢體驗(看看美團外賣小程式那順暢,帶勁)。
那麼我們就做一個整體載入,我們把圖片列表裝在一個容器裡,把容器的透明度設定為0,當我們請求介面並判斷圖片載入完成之後,我們再讓容器漸顯。這時候效果就是四張圖片全部刷的出來了,看下面示例圖(tab切換時更新了列表資料):
一個思路完善但程式碼簡要的例子:
wxml上根據showList來控制載入時顯示動畫,完成顯示容器;
<!-- loading動畫 -->
<block wx:if="{{!showList}}">
<view class='list-loading'>
<image src='loading.gif'></image>
</view>
</block>
<!-- 列表容器 -->
<block hidden="{{!showList}}">
< scroll-view class='contents fade_in}}'>
<navigator wx:for="{{itemList}}" wx:key="item.id" url="{{../specialist/index}}">
<image lazy-load="true" class='list-img' src="{{item.img}}"></image>
</navigator>
</scroll-view>
</block>
js裡控制showList的變化;
Page({
data:{
itemList:[],
showList:false
},
//切換tab時,
switchTab(){
//載入loading動畫
this.setData({
showList:false
});
},
//獲取新tab下的列表
getListItem(){
//...請求介面拿到了新資料的陣列:newList,賦值
this.setData({
itemList:newList
});
//讓圖片載入會,都完事了,再讓圖片容器整體顯示出來吧,所以給個定時器爭取下時間
//250的時間怎麼來的?我說是感覺你會不會打死我。如果你的容器顯示出來的時候圖片還是閃爍載入
//那麼再延長點時間,自己改改感受感受你就知道妙不可言了。
setTimeout(()=>{
this.setData({
showList:true
});
},250);
//微信最近提供了相容性極低的nextTick方法可以代替setTimeout,也許能解決時間全靠估的問題。
//但是我不用,ok?
}
})
在wxss裡,寫個漸顯的動畫過渡效果,在列表容器顯示時過渡一下,圓潤些。
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
以上思路能解決在切換tab或者是大量請求圖片時的圖片載入體驗,如果你不是像我這樣接手的時候程式碼已經被寫好了並且限定你在短時間內做完優化,那麼我建議大量圖片的時候採用預載入,提前把後面的圖片先載入好,不要做這種tab切換時重新替換資料來源的事情,要不得。
如果,我是說如果啊,當你做完這些優化之後,在一些低端安卓機上你的延遲時間需要開到800ms才能保證容器的整體載入,那麼我最後想說的方案,也是我這次優化直接把體驗評分最差D的小程式搞到最棒A的老科技webp
。
webp是什麼,懶得講,自己百度。15k的jpg能給你壓縮到1k(原圖越小壓縮效率越高,原圖越大壓縮效率越低),webp有相容問題,只在chrome系的瀏覽器或者webview裡面能正常工作,也就是說,只有安卓手機的小程式能用webp格式的照片,在ios上是顯示不出來的。
解決方案自然而然的就出來了,根據系統型別判斷該載入什麼格式的圖片,方便起見,在小程式啟動時,設定好全域性變數,以便在各個模組使用。程式碼實現如下:
App({
globalData: {
ios: false
},
//判斷機型
onLaunch: function() {
var vm = this;
var phoneInfo = wx.getSystemInfo({
success: function(res) {
if (res.system.indexOf("iOS") != -1) {
vm.globalData.ios = true
}
}
});
}
})
這樣,在獲取列表之後,根據全域性變數ios的值來給列表圖片賦值相應的路徑,iOS系統使用常規的jpg,png等,android則使用webp格式
完成最後這一步,你會發現現在局勢反過來了,android上的圖片載入速度秒殺iOS,就算你iOS效能好又怎樣,還不是敗給chrome的webp,嘿嘿,又有誰能想到呢。
縱觀網上的所謂的圖片載入的解決方案,當我親身使用之後還是發現不盡人意,差點都拿不出手這個小程式,直到我想到了這麼個方法,用過的都說牛逼,領導一開心,也不抓我做事了,所以我才有時間寫下這篇部落格,幫助後來人。