<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          圖片懶加載從簡單到復(fù)雜

          共 3977字,需瀏覽 8分鐘

           ·

          2020-11-20 18:18

          (給前端大學(xué)加星標(biāo),提升前端技能.

          作者:hateonion

          https://hateonion.me/posts/19jan30/

          圖片懶加載是一個(gè)很重要的前端性能優(yōu)化手段。這篇文章將從懶加載的最簡單場景開始介紹,逐步增加復(fù)雜度,希望能講清楚常見的圖片懶加載場景及在該場景下對應(yīng)的解決辦法,也希望對你有所幫助。

          為什么要做圖片的懶加載

          假設(shè)在用戶訪問某個(gè)頁面時(shí)就加載這個(gè)頁面全部的圖片(即使這些圖片并不處在用戶的當(dāng)前的視窗中),在弱網(wǎng)環(huán)境或者網(wǎng)速較慢的環(huán)境下,這些“冗余”圖片的下載會(huì)占用用戶本來就非常有限的帶寬,傷害用戶體驗(yàn)(比如影響其他資源的下載)。所以對于網(wǎng)站的圖片,理想的做法是懶加載(按需加載)。

          圖片懶加載的原理

          在瀏覽器內(nèi)部對于各種資源有著一套自己的優(yōu)先級定義,瀏覽器會(huì)優(yōu)先加載優(yōu)先級高的資源。
          如果我們不去進(jìn)行圖片的懶加載,默認(rèn)情況下,資源的priority如下。
          這些優(yōu)先級標(biāo)記為high的圖片會(huì)占用其他資源的下載帶寬,可能會(huì)造成某些比較關(guān)鍵的資源(比如xhr call)加載緩慢,拖慢頁面速度。

          圖片懶加載的簡單實(shí)現(xiàn)

          圖片懶加載的思路一般時(shí)當(dāng)頁面加載時(shí)加載一個(gè)尺寸很小的占位圖片(1kb以下),然后再通過js選擇性的去加載真正的圖片。
          一個(gè)最簡單的的實(shí)現(xiàn)如下:
            
          // index.css
          img[src] { filter: blur(0.2em); }
          img { filter: blur(0em); transition: filter 0.5s; }
          (function lazyLoad(){ const imageToLazy = document.querySelectorAll('img[src]'); const loadImage = function (image) { image.setAttribute('src', image.getAttribute('src')); image.addEventListener('load', function() { image.removeAttribute("src"); }) }
          imageToLazy.forEach(function(image){ loadImage(image); })})()
          通過懶加載之后,資源優(yōu)先級如下。

          圖片懶加載的進(jìn)階實(shí)現(xiàn)–滾動(dòng)加載

          上面的方案并不完美,對于用戶來說,不在視窗中的圖片可能根本不是用戶當(dāng)前關(guān)心的圖片,所以我們可以讓這些圖片出現(xiàn)在用戶視窗中再進(jìn)行加載。
          運(yùn)用Intersection Observer 我們可以做到當(dāng)圖片滾動(dòng)到視窗后再加載該圖片。
          (function lazyLoad(){ const imageToLazy = document.querySelectorAll('img[src]'); const loadImage = function (image) { image.setAttribute('src', image.getAttribute('src')); image.addEventListener('load', function() { image.removeAttribute("src"); }) }

          const intersectionObserver = new IntersectionObserver(function(items, observer) { items.forEach(function(item) { if(item.isIntersecting) { loadImage(item.target); observer.unobserve(item.target); } }); });
          imageToLazy.forEach(function(image){ intersectionObserver.observe(image); })})()
          上面的這些demo都在https://github.com/hateonion/lazy-load 這個(gè)repo里面。

          如何選擇合適的Placeholder圖片

          在上面的demo中我們使用了placeholder圖片,實(shí)際上,圖片所占的位置是否確定對于我們選擇placeholder圖片有著很大的影響。

          圖片尺寸已知

          圖片尺寸已知出現(xiàn)的場景一般是博文的題圖或者網(wǎng)站中一些固定尺寸的thumbnail,這些圖的尺寸一般固定且一般不會(huì)發(fā)生改變。對于這種場景,我們可以加載對應(yīng)尺寸的placeholder圖片(如上一節(jié)的demo)。我們可以自己裁剪對應(yīng)尺寸的的placeholder圖片或者使用類似http://placeholder.com/?這樣的服務(wù)來獲取placeholder圖片。

          圖片尺寸未知

          圖片尺寸未知的情況下一般我們需要生成對應(yīng)的thumbnail然后去加載我們生成的thumbnail去做placeholder。為了生成這些thumbnail你可以調(diào)用imagemagick或者調(diào)用一些在線的圖片分割服務(wù)(比如七牛)

          懶加載防止布局抖動(dòng)

          在圖片懶加載時(shí),由于圖片的尺寸不定,瀏覽器難以計(jì)算需要給圖片預(yù)留出的位置。所以當(dāng)圖片加載完成后會(huì)出現(xiàn)網(wǎng)頁布局的抖動(dòng)。
          (image from From?http://davidecalignano.it/lazy-loading-with-responsive-images-and-unknown-height/)
          即使我們選擇的placeholder很小,可以在毫秒級別完成下載,用戶可能意識(shí)不到布局的抖動(dòng)。但是在一些性能比較差的設(shè)備上,這種布局的抖動(dòng)還是會(huì)一定程度上影響用戶的體驗(yàn)。為了完全避免布局閃動(dòng),我們可以采用aspect ratio boxes 的技術(shù)來制作一個(gè)占位用的元素。
          .lazy-load__container{ position: relative; display: block; height: 0;}
          .lazy-load__container.feature { // feature image 的高寬比設(shè)置成42.8% // 對于其他圖片 比如 post圖片,高寬比可能會(huì)不同,可以使用其他css class去設(shè)置 padding-bottom: 42.8%;}
          .lazy-load__container img { position: absolute; top:0; left:0; height: 100%; width: 100%;}
          結(jié)果
          上面這個(gè)實(shí)現(xiàn)的原理其實(shí)很簡單,由于 padding-bottom (或者 padding-top)聲明為百分比時(shí)是根據(jù)元素生成的box的 width 去計(jì)算百分比的,所以我們通過padding-bottom去聲明一個(gè)對應(yīng)高寬比的container。而這個(gè)container的具體尺寸會(huì)由尺寸確定的外層元素確定,但是高寬比始終保持一致。
          而圖片的尺寸設(shè)置成100%container的尺寸保證圖片始終和container的尺寸保持一致。
          需要注意的是上面這個(gè)方法并不能適配圖片比例不一致的網(wǎng)站(比如本站),不過好在,為了用戶體驗(yàn),現(xiàn)在絕大多數(shù)網(wǎng)站的圖片比例都有明確的要求,絕大多數(shù)情況下我們只適配保證網(wǎng)站常用的的幾種圖片寬高比例即可。

          像Medium一樣懶加載圖片

          Medium的懶加載圖片的體驗(yàn)相信去 Medium 讀過文章的同學(xué)都體驗(yàn)過了,可以說是非常的流暢。而其背后的技術(shù)其實(shí)也就是我們上面講到的幾種技術(shù)的組合。
          1. 使用 aspect ratio box 創(chuàng)建占位元素。
          2. 在html解析時(shí)只加載一個(gè)小尺寸的圖片,并且添加blur效果。
          3. 最后使用js選擇性的加載真實(shí)圖片。
          Demo 如下?codePen by José M. Pérez

          總結(jié)

          1. 懶加載用戶當(dāng)前視窗中的圖片可以提升頁面的加載性能。
          2. 懶加載的思路是在html解析時(shí)先加載一個(gè)placeholder圖片,最后再用js選擇性的加載真實(shí)圖片。
          3. 如果需要滾動(dòng)加載可以使用 Intersection Observer 。
          4. 對于固定尺寸和不定尺寸的圖片,我們可以選擇不同的服務(wù)去或者placeholder圖片。
          5. 對于圖片尺寸不確定引起的布局抖動(dòng)問題我們可以使用 aspect ratio box 來解決。

          參考資料

          Progressive Loading
          Lazy loading with responsive images and unknown height
          Simple image placeholders for lazy loading images
          How Medium does progressive image loading
          Sizing Fluid Image Containers with a Little CSS Padding Hack

          瀏覽 68
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产一级a爱做片免费☆观看 | 亚洲无码在线一区 | 无码视频在线免费播放 | 夜夜撸av导航 | 五月色婷婷中文字幕在线 |