IntersectionObserver が見えてきました

IntersectionObservers は、監視対象の要素がブラウザのビューポートに入るか閉じたかを知ることができます。

対応ブラウザ

  • Chrome: 51. <ph type="x-smartling-placeholder">
  • Edge: 15。 <ph type="x-smartling-placeholder">
  • Firefox: 55。 <ph type="x-smartling-placeholder">
  • Safari: 12.1。 <ph type="x-smartling-placeholder">

ソース

たとえば、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 サイクルの使用に注意を払う必要はありません。無限スクローラーを例に考えてみましょう。このシナリオでは、sentinel を DOM に追加し、sentinel を観察(およびリサイクル)することをおすすめします。無限スクローラーの最後のアイテムの近くに標識を追加する必要があります。センチネルが可視化されたら、コールバックを使用してデータを読み込み、次のアイテムを作成して、それらを DOM にアタッチし、それに応じてセンチネルの位置を変更します。センチネルを適切にリサイクルすれば、追加の observe() の呼び出しは不要です。IntersectionObserver は引き続き動作します。

無限スクローラー

その他の更新情報

前述のとおり、コールバックは、確認された要素が部分的にビューに表示されたときと、ビューポートから離れたときとで 1 回トリガーされます。これにより、IntersectionObserver は「要素 X はビュー内にあるか?」という質問の答えを返します。ただし、ユースケースによってはこれでは不十分な場合もあります。

このような場合に役立つのが threshold オプションです。intersectionRatio しきい値の配列を定義できます。intersectionRatio がこれらの値のいずれかと交差するたびに、コールバックが呼び出されます。threshold のデフォルト値は [0] です。これはデフォルトの動作を表しています。threshold[0, 0.25, 0.5, 0.75, 1] に変更すると、要素が 4 分の 1 表示されるようになるたびに通知が届きます。

しきい値のアニメーション。

他の方法はありますか?

現時点では、上記の選択肢以外に選択肢は 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> がその要素の 1 つを監視すると、<iframe> のスクロールと、<iframe> を含むウィンドウのスクロールの両方で、適切なタイミングでコールバックがトリガーされます。ただし後者の場合は、オリジン間でのデータの漏洩を避けるため、rootBoundsnull に設定されます。

IntersectionObserver当てはまらないことは何ですか?

留意すべき点として、IntersectionObserver は意図的にピクセル完全でも低レイテンシでもないということです。スクロール依存型アニメーションのような取り組みを実装するために、データが(厳密に言えば)使用できるようになる頃には古くなっているため、失敗する可能性が高くなります。IntersectionObserver の元のユースケースについての詳細は、説明欄をご覧ください。

コールバックで行える作業の程度

簡潔に言うと、コールバックに長時間を費やすと、アプリの動作が遅くなります。一般的な方法がすべて当てはまります。

要素同士を交差させる

IntersectionObserver はすべての最新ブラウザで使用できるため、ブラウザのサポートは良好です。必要に応じて、古いブラウザでポリフィルを使用でき、WICG のリポジトリから入手できます。当然ながら、このポリフィルを使用しても、ネイティブ実装では得られないパフォーマンス上のメリットは得られません。

今すぐ IntersectionObserver の使用を開始できます。思いついたアイデアをお聞かせください。