Navigate back to the homepage

Observer 好強大 - IntersectionObserver 筆記

JavaScript
December 1st, 2020 · 1 min read

昨天上班接到一個需求是當畫面滑動到某個位置的時候,送出 GA 事件。菜菜的我只想到用 scroll 來監聽去算 offsetTop 等等,主管說可以用 observer 去處理,才發現了強大的 observer。

用 scroll 也不是不行,只是這種方法的缺點是,由於 scroll 事件密集發生,計算量很大,容易造成性能問題。而 observer 可以非同步自動觀察目標物, 就是當目標物出現在觀察器(window)的時候才會 callback,降低了主執行緒(main thread)的負擔 (JS 是 Single Thread 程式),大幅提升效能。

IntersectionObserver HowTo

1. 建立觀察器(observer)

1const observer = new IntersectionObserver(callback, [option]);

2. 可指定參數:callback

callback 就是當目標物(entry)進入到觀察器的鏡頭(root)內時,要做什麼事的 function。

callback 帶進來的都會是陣列,不管觀察的目標物是 1 個或多個

1let callback = (entries, observer) => {
2 entries.forEach((entry) => {
3 // Each entry describes an intersection change for one observed
4 // target element:
5 // entry.boundingClientRect
6 // entry.intersectionRatio
7 // entry.intersectionRect
8 // entry.isIntersecting
9 // entry.rootBounds
10 // entry.target
11 // entry.time
12 });
13};

callback 的項目:

1[
2 {
3 // ReadOnly:目標元素的矩形區域的信息
4 boundingClientRect: {
5 /* ... */
6 },
7
8 // 目標物的可見比例
9 intersectionRatio: 1,
10
11 // ReadOnly:目標物與root的交叉區域
12 intersectionRect: {
13 /* ... */
14 },
15
16 // 是否出現在鏡頭(root))中
17 isIntersecting: true,
18
19 // ReadOnly:鏡頭(root)的資訊
20 rootBounds: {
21 /* ... */
22 },
23
24 // 目標物本身
25 target: 獵物的DOM節點,
26 },
27];

3. 可指定參數:option

option 就是調整觀察器的鏡頭用的。option 是選填,不填就是預設值。如果沒有需求,可以只寫 callback 即可。

1let options = {
2 root: document.querySelector("#scrollArea"),
3 rootMargin: "0px",
4 threshold: 1,
5};
  • root 必須是目標元素的父級元素。root 的預設是 null,root 為 null 時就代表鏡頭就是你的視窗,就是螢幕正在看的區域。

  • rootMargin 的預設值是”0px 0px 0px 0px”。4 個值分別代表上、右、下、左,這個是放大或縮小鏡頭的邊界用的。比方你的螢幕只有 13 寸,但你想讓鏡頭的範圍拉大到 15 寸,這樣就可以讓目標離不開你的視線,那就填 rootMargin 來拉大。

  • threshold 指目標物出現了多少部份在你的鏡頭裡,而出現的部份到了指定的百分比後,都會執行 callback,下面例子則以[0, 0.25, 0.5, 0.75, 1]去做設定。

4. 開始 observe

定義要觀察的目標物,再用建立好的觀察器(observer)去觀察 (observe)即可。 也有另外兩個方法(取消觀察/關閉觀察器)可以去執行。

1let target = document.querySelector(".container");
2observer.observe(target);
  • 開始觀察某個目標物:observer.observe(target);
  • 取消觀察某個目標物:observer.unobserve(target);
  • 關掉這個觀察器:observer.disconnect();

5. demo

1<h1>IntersectionObserver Sample</h1>
2<div class="box box1">box1</div>
3<div class="box box2">box2</div>
4<div class="box box3">box3</div>
1.box {
2 height: 500px;
3 background: #ccc;
4 margin-bottom: 30px;
5}
6
7.box2 {
8 background: #add;
9}
10
11.box3 {
12 background: #809;
13}
1let init = () => {
2 let options = {
3 root: null,
4 rootMargin: "0px",
5 threshold: 1,
6 };
7
8 let callback = (entries) => {
9 entries.forEach((entry) => {
10 if (entry.isIntersecting) {
11 //當目標物進入,即可執行想做的程式
12 let box = entry.target;
13 console.log("entry", entry);
14 console.log("box3", box);
15 }
16 });
17 };
18
19 let observer = new IntersectionObserver(callback, options);
20
21 let target = document.querySelector(".box3");
22
23 observer.observe(target);
24};
25
26init();

https://codesandbox.io/s/intersectionobserver-f7dlt?file=/src/index.js


reference:

https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API https://letswrite.tw/intersection-oserver-basic/ http://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html

圖片來源: https://developers.google.com/web/updates/2016/04/intersectionobserver

More articles from Iris Blog

2019總結 與 2020目標

時間過太快,已經3月了,決定快速寫篇2019回顧,及2020目標。

March 1st, 2020 · 1 min read

什麼是事件委託(Event Delegation)

事件委託,就是利用冒泡原理,把事件監聽器委託給父層,觸發執行。

November 18th, 2021 · 1 min read
© 2020–2021 Iris Blog
Link to $mailto:qweichew@gmail.comLink to $https://github.com/iris1114Link to $https://www.instagram.com/iris.justdoit/Link to $https://www.linkedin.com/in/iris-chew