IntersectionObserver が見えてきました

IntersectionObserver を使用すると、監視対象の要素がブラウザのビューポートに出入りするタイミングを把握できます。

Browser Support

  • Chrome: 51.
  • Edge: 15.
  • Firefox: 55.
  • Safari: 12.1.

Source

たとえば、DOM 内の要素が可視ビューポートに入ったタイミングをトラッキングするとします。この機能は、画像をジャストインタイムで遅延読み込みする場合や、ユーザーが特定の広告バナーを実際に閲覧しているかどうかを把握する必要がある場合に役立ちます。これを行うには、スクロール イベントをフックするか、定期的なタイマーを使用して、その要素で getBoundingClientRect() を呼び出します。

しかし、この方法は非常に時間がかかります。getBoundingClientRect() を呼び出すたびに、ブラウザはページ全体を再レイアウトする必要があるため、ウェブサイトにかなりのジャンクが発生します。サイトが iframe 内に読み込まれていることがわかっていて、ユーザーが要素をいつ表示できるかを知りたい場合、問題はほぼ不可能なものになります。シングル オリジン モデルとブラウザでは、iframe を含むウェブページからデータにアクセスすることはできません。これは、iframe を使用して頻繁に読み込まれる広告などでよく見られる問題です。

この可視性テストをより効率的に行うためにIntersectionObserverが設計され、すべての最新のブラウザに導入されました。IntersectionObserver を使用すると、監視対象の要素がブラウザのビューポートに出入りしたときに通知を受け取ることができます。

iframe の公開設定

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 サイクルを考慮した使用方法ではありません。無限スクロールを例に考えてみましょう。このシナリオでは、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 は今すぐご利用いただけます。どのようなアイデアが浮かんだか教えてください。