最近在做的小程序項(xiàng)目設(shè)計(jì)大量圖片的展示,小程序已經(jīng)提供了圖片的懶加載功能,但是由于圖片本身比較大加上要展示的圖片比較多,如何以一個(gè)比較友好的方式展示未加載完成的過(guò)程就是一個(gè)必須解決的問(wèn)題了。
由于小程序沒(méi)有提供 Image 這個(gè) js 對(duì)象,所以在小程序中實(shí)現(xiàn)預(yù)加載不能直接像原生js 一樣,直接使用 new Image()創(chuàng)建一個(gè)圖片對(duì)象,只能在視圖層創(chuàng)建圖片,通過(guò)onLoad事件監(jiān)聽(tīng)圖片加載完成。
實(shí)現(xiàn)圖片模糊加載的思路就是先加載一個(gè)目標(biāo)圖片的縮略圖,縮略圖的加載一般非??炜梢院雎圆挥?jì),縮略圖加載完成之后以高斯模糊的形式展示,與此同時(shí)加載原圖,原圖加載完成后替代原縮略圖,原圖和縮略圖需要設(shè)置相同的寬高。 思路理清楚之后,開(kāi)始碼代碼吧~
由于項(xiàng)目使用了Taro框架,下面的代碼寫法是React的寫法,原生或者其他框架也可以參考,沒(méi)有太大的出入,思路都是一樣的。
imgLoader.js(以下為部分代碼)
// 監(jiān)聽(tīng)原圖加載完成 toggleOriginLoaded() { this.setState({ loaded: true }); } // 監(jiān)聽(tīng)縮略圖加載完成 toggleThumbLoaded() { this.setState({ thumbLoaded: true }); } render() { let { loaded, thumbLoaded } = this.state; let { imgU, imgW, imgH } = this.props; // 根據(jù)傳入的寬高設(shè)置縮略圖和原圖的寬高 let style = { width: imgW + 'rpx', height: imgH + 'rpx' } return ( <Block> <Image className='image--not-loaded' style={Object.assign({ display: loaded ? 'none' : 'auto' }, style)} lazyLoad mode='aspectFill' onLoad={this.toggleThumbLoaded.bind(this)} src={compressImage(imgU, '10x' + parseInt(imgH * 10 / imgW))} /> {thumbLoaded && ( <Image style={Object.assign({ display: loaded ? 'auto' : 'none' }, style)} lazyLoad className='image--is-loaded' mode='aspectFill' src={imgU} onLoad={this.toggleOriginLoaded.bind(this)} /> )} </Block> ); } 復(fù)制代碼
以上為主要視圖層和邏輯層代碼,其中compressImage函數(shù)是用來(lái)處理圖片剪裁也就是縮略圖的生成的,(ps:我們是用nginx實(shí)現(xiàn)的動(dòng)態(tài)壓縮,裁剪等功能,有需要的小伙伴可以自行搜索相關(guān)教程~)
主要邏輯處理完成之后我們?cè)賮?lái)看模糊樣式的處理,在此就要介紹一個(gè) css 方法 blur()。
blur() CSS方法將高斯模糊應(yīng)用于輸出圖片。它只有一個(gè)接受一個(gè)參數(shù)blur(radius)
radius 表示模糊的半徑,值為length。 它定義了高斯函數(shù)的標(biāo)準(zhǔn)偏差值,即屏幕上有多少像素相互融合; 因此,較大的值會(huì)產(chǎn)生更多模糊。 值為0會(huì)使輸入保持不變。 該值為空則為0。(來(lái)自MDN) 它可以生成類似毛玻璃樣式的圖片,如下圖:
了解了這個(gè)方法之后,就讓我們來(lái)愉快的玩耍(寫代碼)吧~ 我們可以給這個(gè)效果添加一個(gè)小動(dòng)畫,讓它看起來(lái)更有意思哦~
.image--not-loaded{ // fix ios 缺少重繪的問(wèn)題,添加無(wú)意義的transform強(qiáng)制觸發(fā)重繪 transform: scale(1); filter:blur(30px); } .image--is-loaded{ // fix ios 缺少重繪的問(wèn)題,添加無(wú)意義的transform強(qiáng)制觸發(fā)重繪 transform: scale(1); filter:blur(20px); animation: sharpen 0.8s both; } @keyframes sharpen { 0% { filter: blur(20px); } 100% { filter: blur(0px); } } 復(fù)制代碼
需要注意的是blur方法在ios上會(huì)出現(xiàn)無(wú)法正確展示的問(wèn)題,查詢了相關(guān)文章后發(fā)現(xiàn)是因?yàn)閕os 缺少重繪,就是ios不會(huì)根據(jù)這個(gè)代碼重新繪制頁(yè)面因此不能正確展示,如果要解決這個(gè)問(wèn)題只要給他加上一條沒(méi)有意義的transform,強(qiáng)制觸發(fā)重繪就可以了~~
效果圖如下: 5571f524-1f57-43da-