IntersectionObservers 可讓您在觀察到的元素進入或離開瀏覽器可視區域時通知您。
假設您想追蹤 DOM 中的元素進入可見檢視區的時機。我們建議這麼做,以便適時延遲載入圖片,或確定使用者是否確實正在查看特定廣告橫幅。方法是啟動捲動事件,或使用定期計時器,在該元素上呼叫 getBoundingClientRect()
。
不過,這個方法會花費許多時間,因為每次呼叫 getBoundingClientRect()
都會強制瀏覽器重新調整整個網頁的版面配置,為網站帶來大量資源浪費。如果您知道網站正在 iframe 中載入,且您想知道使用者何時能看到特定元素,案件就幾乎是不可能的。「單一來源模型」和瀏覽器無法讓您從含有 iframe 的網頁存取任何資料。這是常見的問題 (例如使用 iframe 載入的廣告)。
IntersectionObserver
是專為所有新式瀏覽器所設計的體驗,想讓這項瀏覽權限測試更有效率。IntersectionObserver
會在觀察到的元素進入或離開瀏覽器的可視區域時通知您。
如何建立 IntersectionObserver
API 規模很小,且最好能舉例說明:
const io = new IntersectionObserver(entries => {
console.log(entries);
}, {
/* Using default options. Details below */
});
// Start observing an element
io.observe(element);
// Stop observing an element
// io.unobserve(element);
// Disable entire IntersectionObserver
// io.disconnect();
如果使用 IntersectionObserver
的預設選項,當元素部分進入檢視畫面及完全離開可視區域時,系統會同時呼叫回呼。
如果您需要觀察多個元素,可以多次呼叫 observe()
來觀察使用相同 IntersectionObserver
例項的多個元素。
entries
參數會傳遞到回呼,這個回呼是 IntersectionObserverEntry
物件的陣列。每個這類物件都包含其中一個觀察元素的最新交集資料。
🔽[IntersectionObserverEntry]
time: 3893.92
🔽rootBounds: ClientRect
bottom: 920
height: 1024
left: 0
right: 1024
top: 0
width: 920
🔽boundingClientRect: ClientRect
// ...
🔽intersectionRect: ClientRect
// ...
intersectionRatio: 0.54
🔽target: div#observee
// ...
rootBounds
是對根元素 (預設為可視區域) 呼叫 getBoundingClientRect()
的結果。boundingClientRect
是對觀察到的元素呼叫 getBoundingClientRect()
的結果。intersectionRect
是這兩個矩形的交集,會有效地告訴您觀察到元素的哪個部分可見。intersectionRatio
具有密切關聯,會顯示元素的顯示比例。有了這些資訊,您現在可以導入素材資源,在素材資源顯示於畫面上之前立即載入內容。效率極佳。
IntersectionObserver
會以非同步方式提供資料,而您的回呼程式碼會在主執行緒中執行。此外,規格實際上表示 IntersectionObserver
實作應使用 requestIdleCallback()
。也就是說,對您提供的回呼進行的呼叫優先順序較低,且會在閒置期間由瀏覽器發出。這是一項謹慎的設計決定。
捲動的 div
我不太喜歡捲動元素內部,但我不是在這裡判斷,也不是IntersectionObserver
。options
物件使用 root
選項,可讓您將可視區域的替代項目定義為根層級。請注意,root
需要是所有觀察元素的祖系。
融入所有元素!
不!這位開發人員可能很糟糕!這並不在乎使用者的 CPU 週期用量。讓我們以無限捲頁為例:在這種情況下,最好將 sentinels 加入 DOM,並觀察 (並回收!) 那些。您應在無限捲動器的最後一個項目附近新增傳送端。當 sentinel 進入檢視畫面後,您可以使用回呼載入資料、建立下一個項目、將這些項目附加至 DOM,並視情況重新放置傳送器。如果正確回收傳送器,則無需額外呼叫 observe()
。IntersectionObserver
可以正常運作。
敬請期待更多最新消息
如前文所述,當觀察到的元素部分進入檢視區塊時,會觸發回呼一次,而另一個則是離開可視區域時。這麼一來,IntersectionObserver
就會回答「顯示 X 元素是否在畫面中?」這個問題的答案。但在某些用途中,這可能不足以滿足您的需求。
這時 threshold
選項就能派上用場。可讓您定義 intersectionRatio
門檻的陣列。每當 intersectionRatio
跨越其中一個值時,系統就會呼叫回呼。threshold
的預設值為 [0]
,表示預設行為。如果將 threshold
變更為 [0, 0.25, 0.5, 0.75, 1]
,每當元素出現額外四分之一的畫面時,我們就會通知我:
還有其他方法嗎?
目前,上述項目只有一個其他選項。rootMargin
可讓您指定根的邊界,有效地擴大或縮小用於交集的區域。這些邊界是使用 CSS 樣式字串 á la "10px 20px 30px 40px"
指定,分別指定上、右、下和左邊界。總結來說,IntersectionObserver
選項結構提供下列選項:
new IntersectionObserver(entries => {/* … */}, {
// The root to use for intersection.
// If not provided, use the top-level document's viewport.
root: null,
// Same as margin, can be 1, 2, 3 or 4 components, possibly negative lengths.
// If an explicit root element is specified, components may be percentages of the
// root element size. If no explicit root element is specified, using a
// percentage is an error.
rootMargin: "0px",
// Threshold(s) at which to trigger callback, specified as a ratio, or list of
// ratios, of (visible area / total area) of the observed element (hence all
// entries must be in the range [0, 1]). Callback will be invoked when the
// visible ratio of the observed element crosses a threshold in the list.
threshold: [0],
});
<iframe>
魔法
IntersectionObserver
是特別為廣告服務和社交網路小工具所設計,這些小工具經常使用 <iframe>
元素,因此不論裝置是否在畫面中顯示,都能因此獲益良多。如果 <iframe>
觀察到其中一個元素,則只要捲動 <iframe>
以及捲動包含 <iframe>
的視窗,系統就會在適當時機觸發回呼。不過,在後者中,rootBounds
會設為 null
,以免來源間外洩。
哪個 IntersectionObserver
「不要」?
需注意的是,IntersectionObserver
原本設計成沒有完美的像素,也不代表低延遲。使用這些動畫實作捲動式動畫等目標時,系統會繫結至失敗,因為資料將會 (嚴格解讀) 沒有時間限制,屆時您才能使用這些資料。如要進一步瞭解 IntersectionObserver
的原始用途,請參閱這篇文章。
我可以在回呼中執行多少工作?
Short 'n Sweet:在回呼中花費太多時間會導致應用程式延遲,而且所有通用做法都適用。
捲動網頁並彼此交錯
瀏覽器支援 IntersectionObserver
,適用於所有新版瀏覽器。必要時,可在舊版瀏覽器中使用 polyfill,並可在 WICG 存放區中找到。顯然,採用原生實作提供的 polyfill 無法享有效能優勢。
現在可以開始使用 IntersectionObserver
了!與我們分享你的想法。