使用交叉點觀察器延遲加載圖像以提升性能【譯】

前言

本文首發於微信公衆號平臺(itclancoder),能夠試試點擊後方使用交叉點觀察期延遲加載圖像以提升性能連接閱讀體驗會更好面試

在本身平時瀏覽一些大量圖片類的網站時,你會發現不管是你pc端下拉滾動條,仍是移動端手動滑屏時,最終呈現的圖片有時候會有所延遲,這是一種預先加載圖片資源的方式,也就是俗稱懶加載,實現該效果,一般有兩種方式,分別是線性式(下拉窗簾式的)和漸進式(撥開晨霧見日明)圖片加載,數組

至於前者這裏暫且不談,本文主要是介紹後者,在本文中主要給img標籤添加一data-src屬性(實際圖片URL),以及src屬性(存儲相同圖像的很是小的分辨率路徑圖片),在加載圖片時,給用戶過分從模糊淡入到圖片清晰.固然更重要的是其中的js處理.若是文有誤導的地方,歡迎路過的老師多提意見和指正瀏覽器

圖片佔據了你網站大小的較高比例。其中一些圖像位於下方,這意味着網站訪問者不會當即看到你的網站。他們須要向下滾動才能查看圖像。若是你只能顯示當即查看的圖像,而後預先加載摺疊下的圖像呢?是的你能夠。這就是這篇文章的內容。某處你必須看到這樣的功能在Medium上bash

考慮圖像源

咱們將在這篇文章中考慮的例子將包含5張或更多圖片,但每一個圖片都會有這種結構服務器

目錄

  1. 考慮圖像源(data-src,與src)
  2. 觀察員(建立實例並使用此實例觀察DOM元素)
  3. 處理交叉路口(條目存儲全部匹配的DOM元素,調用loadImage獲取圖像,而後適當地設置圖像的src)
  4. 其餘考慮事項(模糊轉換爲清晰時,爲圖像添加淡入效果)
  5. 結論(使用漸進式圖片,你能夠減小用戶資源浪費大量時間來下載內容)

代碼:微信

<img src="http://res.cloudinary.com/christekh/image/upload/c_scale,h_3,w_5/v1505391130/wynand-van-poortvliet-364366_gsvyby.jpg" data-src="http://res.cloudinary.com/christekh/image/upload/c_scale,h_300,w_500/v1505391130/wynand-van-poortvliet-364366_gsvyby.jpg" >
複製代碼

每一個標籤都有一個data-src和一個src屬性函數

  1. data-src是咱們但願讀者看到的圖像的實際URL(寬度:500px)
  2. src包含相同圖像的很是小的分辨率(寬度:5px)。這個分辨率將被拉伸以填充空間而且在真實圖像加載時給訪問者模糊的效果。較小的圖像比其小10倍,因此若是全部條件都正常,則會加載速度更快(10倍)

這些圖像存儲在Cloudinary服務器上,能夠經過URL(h_300,w_500或h_3,w_5)輕鬆調整圖像的尺寸post

這是完整的HTML代碼示例性能

<div class="container">
        <!-- Image 1 -->
        <img src="" data-src="" alt="">
        <!-- Image 2 -->
        <img src="" data-src="" alt="">
        <!-- Image 3 -->
        <img src="" data-src="" alt="">
        <!-- Image 4 -->
        <img src="" data-src="" alt="">
        <!-- Image 5 -->
        <img src="" data-src="" alt="">
</div>
複製代碼

觀察員

這是完整的js代碼:fetch

/**
 * 
 * @authors 隨筆川跡 (itclanCode@163.com)
 * @date    2018-03-19 00:58:29
 * @version $Id$
 * @weChatPublicId ((itclanCoder))
 * @QQGroup ((643468880))
 * @PersonWeChatId ((suibichuanji))
 * @PersonQQ ((1046678249))
 * @link ((https://juejin.im/post/5a005392518825295f5d53c8))
 * @describe 使用交叉點觀察器延遲加載圖像以提升性能js代碼
 */
// 獲取img標籤元素
const images = document.querySelectorAll('img');

// 選項options
const options = {
  // 若是圖像在Y軸上達到50像素之內,請開始下載 If the image gets within 50px in the Y axis, start the download.
  root: null, // 以頁面做爲根元素 Page as root
  rootMargin: '0px',
  threshold: 0.1
};
// 取得圖片
const fetchImage = (url) => {
  console.log(url);
  return new Promise((resolve, reject) => {
    const image = new Image();
    image.src = url;
    image.onload = resolve;
    image.onerror = reject;
  });
}
// 加載圖片
const loadImage = (image) => {
  const src = image.dataset.src;
  fetchImage(src).then(() => {
    // console.log(src)
    image.src = src;
  })
}
// 處理交叉路口,entries表明條目,observer觀察者
const handleIntersection = (entries, observer) => {
  entries.forEach(entry => {
    if(entry.intersectionRatio > 0) {
      console.log(entry.intersectionRatio);
      loadImage(entry.target)
    }
  })
}

// 頁面上圖像的觀察者 The observer for the images on the page
const observer = new IntersectionObserver(handleIntersection, options);

images.forEach(img => {
  observer.observe(img);
})
複製代碼

觀察者是交集觀察者的一個實例。你建立實例並使用此實例觀察DOM元素。你能夠觀察元素什麼時候進入視口

const options = {
      rootMargin:'0px',
      threshold:0.1
   }
   const observer = new IntersectionObserver(handleIntersection,options);
複製代碼

該實例須要一個處理程序和一個選項參數。處理程序是當匹配交叉點發生時調用的函數,而options參數定義了觀察者的行爲。在這種狀況下,咱們但願處理器在圖像進入視口後當即被調用(閾值:0.1)

你可使用觀察者觀察頁面中的全部圖像

const images = document.querySelectorAll('img');
   images.forEach(img => {
       observer.observe(img);
    })
複製代碼

處理交叉路口

咱們爲處理程序使用了一個方法,但沒有定義它。這將會像預期的那樣尖叫一個錯誤。讓咱們在實例上建立處理程序

const handleIntersection = (entries,observer) =>{
        entries.forEach(entry =>{
            if(entry.intersectionRatio > 0){
                loadImage(entry.target);
            }
        }

        )
    }

複製代碼

該方法由帶有條目數組和觀察者實例的API調用。條目存儲全部匹配的DOM元素(在這種狀況下爲imgs)的一個實例。若是匹配,咱們用元素調用loadImage

loadImage獲取圖像,而後適當地設置圖像的src

const loadImage = (image) => {
      const src = image.dataset.src;
      fetchImage(src).then(() => {
         image.src = src;
      })
   }

複製代碼

它經過使用data-src值調用fetchImage方法來完成此操做。當實際圖像返回時,它會設置image.src的值

fetchImage獲取圖像並返回一個承諾

const fetchImage = (url) => {
        return new Promise((resolve,reject) => {
           const image = new Image();
           img.src = url;
           image.onload = resolve;
           image.onerror = reject;
        })
    }

複製代碼

其餘考慮事項

考慮到流暢的用戶體驗,當從模糊轉換爲清晰時,你還能夠爲圖像添加淡入效果。若是觀看者認爲加載時間較慢,這使得它更吸引眼睛

請注意,Intersection Observer在全部瀏覽器中都不被普遍支持,所以你可能會考慮使用填充或在頁面加載後自動加載圖像

if('IntersectionObserver' in window){
      // observer code
      const observer = new IntersectionObserver(handleIntersection,options);
   }else{
       Array.from(images).forEach(image => loadImage(image))
   }
複製代碼

結論

使用漸進式圖片,你能夠減小用戶資源浪費大量時間來下載內容,其實也就是預先加載資源更小的資源,策略就是減小文件的體積,按部就班的加載,減小帶寬,從而提升頁面的訪問速度,這在面試當中不妨也是一種優化頁面性能的答覆,固然還有其餘?若知後文,關注微信itclanCoder公衆號便可,下一篇內容繼續揭曉...

原文連接

能夠試試點擊後方使用交叉點觀察期延遲加載圖像以提升性能連接閱讀體驗會更好

相關文章
相關標籤/搜索