天天看點

使用高斯模糊的效果逐漸加載圖檔(仿 Medium)

使用高斯模糊的效果逐漸加載圖檔(仿 Medium)

用過 medium 的使用者不會不記得它的圖檔加載方式——純色-高斯模糊-加載完成并顯示。

這是一種很優雅的圖檔預加載的方式(因為 medium 的圖檔品質都很高,如果全部一下加載的話,需要的時間難以想象,是以,這是一種很棒的做法)。從第一次打開 medium 這個網站開始,我就被這種技術給吸引住了——好吧,直到今天才去研究它。

在 medium 網站,打開任何一篇文章,然後,我們來 inspect 一下:

<figure name="512a"  

        id="512a"  

        class="graf--figure graf--layoutcroppedheightpreview graf-after--h3" 

> 

    <div class="aspectratioplaceholder is-locked"> 

        <div class="aspectratioplaceholder-fill"  

             style="padding-bottom: 30%;" 

        ></div> 

        <div class="progressivemedia js-progressivemedia graf-image is-canvasloaded"  

             data-image-id="1*dznfezixxf2bgn3vsquola.jpeg"  

             data-width="3600"  

             data-height="3600"  

             data-scroll="native" 

        > 

            <img src="https://cdn-images-1.medium.com/freeze/fit/t/60/18/1*dznfezixxf2bgn3vsquola.jpeg?q=20"  

                 crossorigin="anonymous"  

                 class="progressivemedia-thumbnail js-progressivemedia-thumbnail" 

            > 

            <canvas class="progressivemedia-canvas js-progressivemedia-canvas"  

                    width="75"  

                    height="22" 

            ></canvas> 

            <img class="progressivemedia-image js-progressivemedia-image"  

                 data-src="https://cdn-images-1.medium.com/fit/t/1600/480/1*dznfezixxf2bgn3vsquola.jpeg"  

                 src="https://cdn-images-1.medium.com/fit/t/1600/480/1*dznfezixxf2bgn3vsquola.jpeg" 

            <noscript class="js-progressivemedia-inner"> 

                <img class="progressivemedia-noscript js-progressivemedia-inner" src="https://cdn-images-1.medium.com/fit/t/1600/480/1*dznfezixxf2bgn3vsquola.jpeg"> 

            </noscript> 

        </div> 

    </div> 

</figure>  

可以看到,medium 為每一張圖檔都設定了這麼長的一段 html。這樣做的目的就是為了讓這個圖檔的逐漸加載過程能夠平滑如一,同時還能在一定程度上提升使用者體驗。就算圖檔沒有加載出來,顯示給使用者的是一個高斯模糊的圖檔,其實也不失美感。

那麼,這個圖檔的逐漸加載過程具體是什麼樣的呢?

渲染一個 div 容器,這個容器就是用來顯示最終展示給使用者的圖檔的。通過對容器設定一個百分比的 padding-bottom 來讓其比例和大小與最終圖檔的比例和大小相同,這樣,就能避免圖檔加載出來的時候導緻的頁面的重排;

使用 img 标簽來加載一張原圖品質的 10% ~ 20% 左右的圖檔,這張圖檔的品質很低,而且很小,是以可以馬上加載出來;

一旦小圖加載完成,就開始使用 canvas 來進行繪制,添加模糊效果,同時,開始請求最終要加載的大圖;

當最終的大圖也加載完成之後,顯示大圖,隐藏掉 canvas。

以上就是 medium 的做法。

我們可以自己來實作這個效果,實作過程如下:

渲染一個容器,保持與原圖的比例和尺寸相同,填充一個較淺的背景色;

先加載小圖,同時使用模糊效果;

小圖加載完成,開始請求大圖;

大圖加載完成,顯示大圖,隐藏小圖。

是以,綜合來看,其實并不複雜。

首先,我們可以把大圖和小圖的 url 和尺寸都存起來,通過标簽的 data 屬性去動态擷取。是以,我們的 html 可以像下面這樣寫:

<figure name="blur" 

        class="blur-img-container" 

        data-real-width="1174" 

        data-real-height="670" 

        data-src="images/sm2.jpeg" 

        src="https://cdn-images-1.medium.com/max/2000/1*0wwtdke1q6hgzwd6kn9suq.jpeg" 

></figure>  

其中各個參數代表的含義是:

data-real-width: 大圖的寬度

data-real-height: 大圖的高度

data-src: 小圖的 url

src: 大圖的 url

同時,我們需要定義一些 css 的 class 來對大圖和小圖進行處理:

.blur-img-container { 

    position: relative; 

    background: #eeeeee; 

    background-size: cover; 

    overflow: hidden; 

.blur-img-container img { 

    position: absolute; 

    top: 0; 

    left: 0; 

    width: 100%; 

    height: 100%; 

    opacity: 0; 

    transition: all 0.4s ease-in-out; 

.blur-img-container .thumb-loaded { 

    opacity: 1; 

    filter: blur(10px); 

    transform: scale(1); 

.blur-img-container .large-loaded { 

.blur-img-container .thumb-hidden { 

}  

然後,我們的重點在于 javascript 的處理。

需要動态的設定每個圖檔的容器的 padding-bottom 以防止頁面發生重排;

通過 image 的 onload 事件來控制其樣式和進度

第一點,動态設定我們的容器的 padding-bottom。可以通過計算寬高比然後換算成百分比:

elem.style.paddingbottom = `${(realheight / realwidth) * 100}%`; 

第二點,使用圖像的 onload 事件來控制加載的進度:

let thumb = new image(); 

thumb.src = thumbsrc; 

thumb.onload = () => { 

    // 小圖加載完成,顯示小圖,設定樣式 

    setstyle(thumb, 'thumb-loaded'); 

}; 

elem.appendchild(thumb); 

let realimg = new image(); 

realimg.src = lgsrc; 

realimg.onload = () => { 

    // 大圖加載完成,顯示大圖,隐藏小圖 

    setstyle(realimg, 'large-loaded'); 

    setstyle(thumb, 'thumb-hidden'); 

// 将大圖添加到頁面中 

elem.appendchild(realimg);  

其實,隻要把上面兩點主要的功能做好了,我們的這個效果基本上就實作了。

同時,我将這個小功能封裝成了一個 package,需要的朋友可以通過 npm install blur-image 或者 bower install blur-image 進行安裝和使用。具體的安裝和使用方法可以檢視文檔。

作者:erichain_zain

來源:51cto

繼續閱讀