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
は、これら 2 つの長方形の交差であり、監視対象の要素のどの部分が表示されているかを効果的に判断できます。intersectionRatio
はこれに関連しており、要素の表示範囲を示します。この情報を自由に利用できるため、アセットが画面に表示される前のジャストインタイムの読み込みなどの機能を実装できるようになりました。効率的である。
IntersectionObserver
はデータを非同期で配信し、コールバック コードはメインスレッドで実行されます。また、仕様では、IntersectionObserver
の実装で requestIdleCallback()
を使用する必要があると明記されています。つまり、指定したコールバックへの呼び出しの優先度は低く、ブラウザはアイドル時に呼び出しを行います。これは意図的な設計上の決定です。
div のスクロール
要素内のスクロールはあまり好きではありませんが、判断するのは私ではなく、IntersectionObserver
でもありません。options
オブジェクトは root
オプションを取ります。このオプションを使用すると、ビューポートの代わりにルートを定義できます。root
は、検出されたすべての要素の祖先である必要があります。
すべてのものを交差させましょう。
いいえ。デベロッパーが悪い!ユーザーの CPU サイクルの使用に注意を払う必要はありません。無限スクロールを例に考えてみましょう。このシナリオでは、DOM にセンチネルを追加して、それらを監視(およびリサイクル)することを強くおすすめします。無限スクローラーの最後のアイテムの近くに標識を追加する必要があります。そのセレンティールが視界に入ると、コールバックを使用してデータを読み込み、次のアイテムを作成し、DOM に接続して、セレンティールの位置を適宜調整できます。センチネルを適切にリサイクルすれば、追加の observe()
の呼び出しは不要です。IntersectionObserver
は引き続き動作します。
最新情報を教えてください
前述のように、コールバックは、監視対象の要素が部分的にビューに表示されたときに 1 回、ビューポートから消えたときに 1 回トリガーされます。これにより、IntersectionObserver
は「要素 X はビュー内にあるか?」という質問に回答します。ただし、ユースケースによっては、それだけでは不十分な場合があります。
そこで threshold
オプションの出番です。intersectionRatio
しきい値の配列を定義できます。コールバックは、intersectionRatio
がこれらの値のいずれかを越えるたびに呼び出されます。threshold
のデフォルト値は [0]
です。これはデフォルトの動作を表しています。threshold
を [0, 0.25, 0.5, 0.75, 1]
に変更すると、要素の 1/4 が追加で表示されるたびに通知が届きます。
他の方法はありますか?
現時点では、上記のオプションに加えて選択できるオプションは 1 つだけです。rootMargin
を使用すると、ルートの余白を指定できるため、交差点に使用される領域を効果的に拡大または縮小できます。これらの余白は、上、右、下、左の余白をそれぞれ指定する CSS スタイルの文字列 á la "10px 20px 30px 40px"
を使用して指定します。まとめると、IntersectionObserver
options 構造体には、次のオプションがあります。
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
Not とは
IntersectionObserver
は、意図的にピクセル パーフェクトでも低レイテンシでもないことに注意してください。スクロール依存型アニメーションのような取り組みを実装するために、データが(厳密に言えば)使用できるようになる頃には古くなっているため、失敗する可能性が高くなります。IntersectionObserver
の元のユースケースの詳細については、説明をご覧ください。
コールバックで行える作業の程度
簡潔に: コールバックで時間を長く取るとアプリが遅くなります。一般的な方法がすべて適用されます。
要素を交差させる
IntersectionObserver
はすべての最新ブラウザで利用可能であるため、ブラウザでのサポートは良好です。必要に応じて、古いブラウザでポリフィルを使用できます。ポリフィルは WICG のリポジトリで入手できます。当然、ポリフィルを使用すると、ネイティブ実装で得られるパフォーマンス上のメリットは得られません。
IntersectionObserver
はすぐにご利用いただけます。考えたアイデアをお知らせください。