IntersectionObserver を使用すると、観測された要素がブラウザのビューポートに入ったか、出て行くと通知されます。
たとえば、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
オブジェクトの配列です。これらの各オブジェクトには、観測された要素の 1 つについて更新された交差点データが含まれています。
🔽[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
はこれら 2 つの長方形の交差部分で、観測された要素のどの部分が表示されているかを効果的に示します。intersectionRatio
は密接に関連しており、要素がどの程度見えるかを示します。この情報を活用すれば、アセットが画面に表示される前にジャストインタイムで読み込むなどの機能を実装できます。効率的。
IntersectionObserver
はデータを非同期で配信し、コールバック コードはメインスレッドで実行されます。さらに、仕様には実際に、IntersectionObserver
の実装で requestIdleCallback()
を使用する必要があることが示されています。つまり、指定したコールバックは優先度が低く、アイドル時にブラウザによって呼び出されます。これは意識的な設計上の決定です。
div のスクロール
私は要素内をスクロールすることはあまり好きではありませんが、判断はしませんし、IntersectionObserver
も好きではありません。options
オブジェクトは、ビューポートの代替をルートとして定義できる root
オプションを受け取ります。root
は、観測されるすべての要素の祖先にする必要があります。
すべてのものを交差させる!
いいえ。悪い開発者だ!これは、ユーザーの CPU サイクルを慎重に使用しているとは言えません。無限スクローラーを例に考えてみましょう。このシナリオでは、Sentinels を DOM に追加し、監視(リサイクル)することが絶対におすすめです。無限スクローラーの最後のアイテムの近くに標識を追加する必要があります。その標識が表示されたら、コールバックを使用してデータを読み込み、次のアイテムを作成して DOM にアタッチし、それに応じて標識の位置を変更します。標識を適切にリサイクルできれば、observe()
への追加の呼び出しは必要ありません。IntersectionObserver
は引き続き動作します。
最新情報をお寄せください
前述のように、コールバックは監視対象の要素が部分的にビューに入ったときに 1 回トリガーされ、もう 1 回はビューポートから外れたときにトリガーされます。このようにして、IntersectionObserver
は「要素 X は表示範囲内にあるか」という質問に対する答えを提供します。ただし、これだけでは不十分なユースケースもあります。
そこで役立つのが threshold
オプションです。これにより、intersectionRatio
しきい値の配列を定義できます。intersectionRatio
がこれらの値のいずれかを横切るたびに、コールバックが呼び出されます。threshold
のデフォルト値は [0]
です。これがデフォルトの動作になります。threshold
を [0, 0.25, 0.5, 0.75, 1]
に変更すると、要素のさらに 4 分の 1 が表示されるたびに通知を受け取ります。
他の選択肢はありますか?
現在のところ、上記の選択肢以外に選択肢が 1 つしかありません。rootMargin
を使用すると、ルートのマージンを指定できるため、交差点に使用される領域を効果的に拡大または縮小できます。これらのマージンは、CSS スタイルの文字列 "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>
がその要素の 1 つを監視している場合、<iframe>
のスクロールと、<iframe>
を含むウィンドウのスクロールの両方で、適切なタイミングでコールバックがトリガーされます。ただし、後者の場合は、オリジン間でデータが漏洩しないように、rootBounds
を null
に設定します。
IntersectionObserver
が重要でない点
IntersectionObserver
は意図的に、ピクセル パーフェクトでも低レイテンシでもないことに注意してください。これらを使用してスクロール依存のアニメーションなどの実装を行うと、失敗に終わります。厳密に言えば、データを使用できるようになる頃にはデータが古くなってしまうからです。IntersectionObserver
の元のユースケースについては、説明で詳しく説明しています。
コールバックではどの程度の作業を行えますか?
短い説明: コールバックに時間をかけすぎると、アプリの処理が遅くなります。これは一般的なやり方です。
前に進み、要素と交差する
IntersectionObserver
がすべての最新ブラウザで利用できるため、サポートは良好です。必要に応じて、ポリフィルを古いブラウザで使用することもできます。ポリフィルは WICG のリポジトリから入手できます。もちろん、そのポリフィルを使用すると、ネイティブ実装では得られないパフォーマンス上のメリットは得られません。
IntersectionObserver
を今すぐご利用いただけます。どのようなアイデアが浮かんだか教えてください。