這是個還在草案中的API,不過大部分瀏覽器均已實現(除了IE)。先看下MDN中的介紹:javascript
IntersectionObserver接口提供了一種異步觀察目標元素與祖先元素或頂級文檔viewport的交集中的變化的方法。祖先元素與視窗viewport被稱爲根(root)。html
不知你們有沒有發現隨着網頁發展,對檢測某個(些)元素是否出如今可視窗相關的需求愈來愈多了?好比:java
一直以來,檢測元素的可視狀態或者兩個元素的相對可視狀態都不是件容易事,大部分解決辦法並不徹底可靠,實現方式很醜陋,也極易拖慢整個網站的性能。web
IntersectionObserver正所以而生數組
是以new
的形式聲明一個對象,接收兩個參數callback
和options
瀏覽器
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)
複製代碼
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 的時間原點到交叉被觸發的時間的時間戳 |
表格中加粗的兩個屬性是比較經常使用的判斷條件:isIntersecting和intersectionRatioide
options是一個對象,用來配置參數,也能夠不填。共有三個屬性,具體以下:函數
屬性 | 說明 |
---|---|
root | 所監聽對象的具體祖先元素。若是未傳入值或值爲null ,則默認使用頂級文檔的視窗(通常爲html)。 |
rootMargin | 計算交叉時添加到根(root)邊界盒bounding box的矩形偏移量, 能夠有效的縮小或擴大根的斷定範圍從而知足計算須要。全部的偏移量都可用像素(px )或百分比(% )來表達, 默認值爲"0px 0px 0px 0px"。 |
threshold | 一個包含閾值的列表, 按升序排列, 列表中的每一個閾值都是監聽對象的交叉區域與邊界區域的比率。當監聽對象的任何閾值被越過期,都會觸發callback。默認值爲0。 |
介紹了這麼多配置項及參數,差點忘了最重要的,IntersectionObserver有哪些方法? 若是要監聽某些元素,則必需要對該元素執行一下observe性能
方法 | 說明 |
---|---|
observe() | 開始監聽一個目標元素 |
unobserve() | 中止監聽特定目標元素 |
takeRecords() | 返回全部觀察目標的IntersectionObserverEntry對象數組 |
disconnect() | 使IntersectionObserver對象中止所有監聽工做 |
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))
複製代碼
假若有個需求,對一個頁面中的特定元素,只有在其徹底顯示在可視區內時進行埋點曝光。
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))
複製代碼
用上面的例子隨便寫了一個,太醜勿噴
總之,這是一個至關方便好用的API!
參考連接🔗