超好用的API之IntersectionObserver

IntersectionObserver

這是個還在草案中的API,不過大部分瀏覽器均已實現(除了IE)。先看下MDN中的介紹:javascript

IntersectionObserver接口提供了一種異步觀察目標元素與祖先元素或頂級文檔viewport的交集中的變化的方法。祖先元素與視窗viewport被稱爲根(root)。html

目標元素與視窗

不知你們有沒有發現隨着網頁發展,對檢測某個(些)元素是否出如今可視窗相關的需求愈來愈多了?好比:java

  • 當頁面滾動時,懶加載圖片或其餘內容。
  • 實現「可無限滾動」網站,也就是當用戶滾動網頁時直接加載更多內容,無需翻頁。
  • 對某些元素進行埋點曝光
  • 滾動到相應區域來執行相應動畫或其餘任務。

一直以來,檢測元素的可視狀態或者兩個元素的相對可視狀態都不是件容易事,大部分解決辦法並不徹底可靠,實現方式很醜陋,也極易拖慢整個網站的性能。web

IntersectionObserver正所以而生數組

API解讀:

1.用法

是以new的形式聲明一個對象,接收兩個參數callbackoptions瀏覽器

const io = new IntersectionObserver(callback, options)

io.observe(DOM)
複製代碼
const options = {
  root: null,
  rootMargin: 0,
  thresholds: 1,
}
const io = new IntersectionObserver(entries => {
  console.log(entries)
  // Do something
}, options)
複製代碼

2.callback

callback是添加監聽後,當監聽目標發生滾動變化時觸發的回調函數。接收一個參數entries,即IntersectionObserverEntry實例。描述了目標元素與root的交叉狀態。具體參數以下:異步

屬性 說明
boundingClientRect 返回包含目標元素的邊界信息,返回結果與element.getBoundingClientRect() 相同
intersectionRatio 返回目標元素出如今可視區的比例
intersectionRect 用來描述root和目標元素的相交區域
isIntersecting 返回一個布爾值,下列兩種操做均會觸發callback:1. 若是目標元素出如今root可視區,返回true。2. 若是從root可視區消失,返回false
rootBounds 用來描述交叉區域觀察者(intersection observer)中的根.
target 目標元素:與根出現相交區域改變的元素 (Element)
time 返回一個記錄從 IntersectionObserver 的時間原點到交叉被觸發的時間的時間戳

表格中加粗的兩個屬性是比較經常使用的判斷條件:isIntersectingintersectionRatioide

IntersectionObserverEntry打印的值

3.options

options是一個對象,用來配置參數,也能夠不填。共有三個屬性,具體以下:函數

屬性 說明
root 所監聽對象的具體祖先元素。若是未傳入值或值爲null,則默認使用頂級文檔的視窗(通常爲html)。
rootMargin 計算交叉時添加到根(root)邊界盒bounding box的矩形偏移量, 能夠有效的縮小或擴大根的斷定範圍從而知足計算須要。全部的偏移量都可用像素(px)或百分比(%)來表達, 默認值爲"0px 0px 0px 0px"。
threshold 一個包含閾值的列表, 按升序排列, 列表中的每一個閾值都是監聽對象的交叉區域與邊界區域的比率。當監聽對象的任何閾值被越過期,都會觸發callback。默認值爲0。

4.方法

介紹了這麼多配置項及參數,差點忘了最重要的,IntersectionObserver有哪些方法? 若是要監聽某些元素,則必需要對該元素執行一下observe性能

方法 說明
observe() 開始監聽一個目標元素
unobserve() 中止監聽特定目標元素
takeRecords() 返回全部觀察目標的IntersectionObserverEntry對象數組
disconnect() 使IntersectionObserver對象中止所有監聽工做

應用:

1.圖片懶加載

const imgList = [...document.querySelectorAll('img')]

var io = new IntersectionObserver((entries) =>{
  entries.forEach(item => {
    // isIntersecting是一個Boolean值,判斷目標元素當前是否可見
    if (item.isIntersecting) {
      item.target.src = item.target.dataset.src
      // 圖片加載後即中止監聽該元素
      io.unobserve(item.target)
    }
  })
}, {
  root: document.querySelector('.root')
})

// observe遍歷監聽全部img節點
imgList.forEach(img => io.observe(img))
複製代碼

2.埋點曝光

假若有個需求,對一個頁面中的特定元素,只有在其徹底顯示在可視區內時進行埋點曝光。

const boxList = [...document.querySelectorAll('.box')]

var io = new IntersectionObserver((entries) =>{
  entries.forEach(item => {
    // intersectionRatio === 1說明該元素徹底暴露出來,符合業務需求
    if (item.intersectionRatio === 1) {
      // 。。。 埋點曝光代碼
      io.unobserve(item.target)
    }
  })
}, {
  root: null,
  threshold: 1, // 閥值設爲1,當只有比例達到1時才觸發回調函數
})

// observe遍歷監聽全部box節點
boxList.forEach(box => io.observe(box))
複製代碼

3.滾動動畫

用上面的例子隨便寫了一個,太醜勿噴

IntersectionObserver.gif

總之,這是一個至關方便好用的API!

參考連接🔗

MDN: IntersectionObserver

MDN: IntersectionObserverEntry

相關文章
相關標籤/搜索