From 33a4f2ab92ac50885761e68f0246fd0d9f56a500 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Thu, 24 Feb 2022 01:54:05 +0900 Subject: 2022/02/10 時点の英語版に同期 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ja/web/api/intersection_observer_api/index.md | 579 +++++++++++---------- 1 file changed, 290 insertions(+), 289 deletions(-) diff --git a/files/ja/web/api/intersection_observer_api/index.md b/files/ja/web/api/intersection_observer_api/index.md index 7763ec2725..8253161111 100644 --- a/files/ja/web/api/intersection_observer_api/index.md +++ b/files/ja/web/api/intersection_observer_api/index.md @@ -1,90 +1,95 @@ --- -title: Intersection Observer API +title: 交差オブザーバー API slug: Web/API/Intersection_Observer_API tags: - API - Clipping - - Intersection - - Intersection Observer API - - IntersectionObserver - - Overview - - Performance - - Reference - - Web - 交差 - - 交差監視 + - 交差オブザーバー API + - IntersectionObserver + - 概要 + - パフォーマンス + - リファレンス + - ウェブ translation_of: Web/API/Intersection_Observer_API --- -
{{DefaultAPISidebar("Intersection Observer API")}}
+{{DefaultAPISidebar("Intersection Observer API")}} + +交差オブザーバー API (Intersection Observer API) は、ターゲットとなる要素が、祖先要素または文書の最上位の{{Glossary("viewport", "ビューポート")}}と交差する変化を非同期的に監視する方法を提供します。 -

Intersection Observer API (交差監視 API) は、ターゲットとなる要素が、祖先要素もしくは文書の最上位の{{Glossary("viewport", "ビューポート")}}と交差する変更を非同期的に監視する方法を提供します。

+従来、ある要素の可視状態、あるいは 2 つの要素の相対的な可視状態を検出することは困難であり、その解決策は信頼性が低く、ブラウザーやアクセスするサイトの動作が重くなる傾向がありました。ウェブが成熟していくにつれて、このような情報の必要性は高まっていきます。交差情報 (Intersection information) についての情報は次の理由から必要とされています。 -

従来、要素の可視性や、二つの要素間で互いに相対的な可視性を検出することは難しく、どの解決方法も不確実であり、ブラウザーやユーザーがアクセスするサイトの反応を鈍くする要因の一つとなっていました。ウェブが成熟していくにつれてこのような情報の必要性は高まっていきます。 Intersection (要素間交差) についての情報は下記のような理由から必要とされています。

+- ページがスクロールした際の画像やその他のコンテンツの遅延読み込み。 +- 「無限スクロール」をするウェブサイトを実装し、スクロールに従って次々とコンテンツを読み込んで、ユーザーがページの切り替えをせずに済むようにすること。 +- 広告費を計算するための広告が表示されたかどうかのレポート。 +- ユーザーが結果を見るかどうかで、タスクを実行するかどうか、アニメーションを処理するかどうかを決定すること。 - +以前は、要素同士の交差の検出を実装するには、イベントハンドラーやループで {{domxref("Element.getBoundingClientRect()")}} などのメソッドを呼び出し、影響を受けるすべての要素について必要な情報を蓄積していました。このコードはすべてメインスレッドで実行されるため、これらのうち 1 つでもあればパフォーマンスの問題を引き起こす可能性があります。サイトでこのような検出が大量に行われると、まったく醜くなる可能性があります。 -

これまで、要素間の交差を検出する実装をするには、 {{domxref("Element.getBoundingClientRect()")}} のようなメソッドを呼び出すイベントハンドラーやループがあり、影響を受ける要素に対する情報を都度計算し集めることで構成されていました。このようなコードがメインスレッドで実行されると、いずれかはパフォーマンスの問題を引き起こす可能性があります。試しにサイトにテストとして読み込めば分かりますが、事態は完全に酷くなりえます。

+ウェブページで無限スクロールを使用することを考えてみてください。ベンダーから提供されるライブラリーを使用して、ページ全体に定期的に配置された広告を管理し、アニメーショングラフィックスを表示し、通知ボックスなどを描画するカスタムライブラリーを使用します。それぞれには独自に交差を検出するためのルーチンがあり、すべてがメインスレッド上で実行されます。ウェブサイトの作者は、これが起こっていることを認識していないかもしれません。内部の働きについてほとんど知らずに 2 つのライブラリーを使用しているからです。ユーザーがページをスクロールすると、スクロール処理中にこれらの交差の検出ルーチンが絶えず起動し、ユーザーはブラウザー、ウェブサイト、およびコンピューターにイライラさせられることになります。 -

ウェブページで無限スクロールを使用することを考えてみてください。ベンダーから提供されるライブラリを使用して、ページ全体に定期的に配置された広告を管理し、アニメーショングラフィックスを表示し、通知ボックスなどを描画するカスタムライブラリを使用します。これらのそれぞれには独自の Intersection を検出するためのルーチンがあり、すべてがメインスレッド上で実行されます。ウェブサイトの作者は、これが起こっていることを認識していないかもしれません。なぜなら、彼らは内部の働きについてほとんど知らずに2つのライブラリを使用しているからです。ユーザーがページをスクロールすると、スクロール処理中にこれらの Intersection の検出ルーチンが絶えず起動し、ユーザーはブラウザー、ウェブサイト、およびコンピュータにイライラさせられることになります。

+交差オブザーバー API では、監視したい要素が他の要素(または{{Glossary("viewport", "ビューポート")}})に入ったり出たりしたとき、あるいは両者が交差する量が要求された量だけ変化したときに実行されるコールバック関数をコードに登録することができます。この方法により、サイトはこの種の要素の交差を監視するためにメインスレッドで何もする必要がなくなり、ブラウザーは自由に交差の管理を最適化することができます。 -

Intersection Observer API を使用することで、監視したい要素が別の要素 (もしくは{{Glossary("viewport")}}) に入ってきたり出ていったりする時、まだ両要素が交差する量がある一定の量を満たす時、実行されるコールバック関数を登録するが出来ます。こういった方法を用いることで、この手の要素交差を監視するためにサイトはメインスレッド上で何もする必要がなくなり、ブラウザーは要素間交差の管理を最適化して自由に行えます。

+交差オブザーバー API は、重複したピクセルの正確な数や、それがどのピクセルであるかを具体的に示すことはできません。しかし、「_N_ % 前後のどこかで交差していたら、何かをする必要がある」という、より一般的な利用法はカバーします。 -

Intersection Observer API を使用してできないものの1つは、重複するピクセル数または具体的なピクセル数です。ただし、「N%前後のどこかで交差する場合に何かしたい」という一般的な利用法はカバーされています。

+## 交差オブザーバーの概念と使い方 -

Intersection observer 概念と使い方

+交差オブザーバー API を使用すると、以下のいずれかの状況が発生したときに呼び出されるコールバックを構成することができます。 -

Intersection Observer API を使用すると、ある要素が、これをターゲットと呼びますが、端末のビューポートまたは指定された要素 - API の目的からこれをルート要素もしくはルートと呼びます - と交差するたびに呼び出されるコールバックを構成することができます。通常は、要素の直近のスクロール可能な祖先、または、要素がスクロール可能な要素の子孫でない場合はビューポートに関する交差状態の変更を監視したいでしょう。ルート要素に関する交差を監視するには、 null を指定してください。

+- **ターゲット**要素が端末のビューポートまたは指定された要素と交差すること。この指定された要素は、交差オブザーバー API の用途では**ルート要素**または**ルート**と呼びます。 +- オブザーバーがターゲット要素を監視するよう最初に指示されたとき。 -

ビューポートとその他の要素のどちらがルートとして使用されていても、 API は同じように動作し、ターゲット要素の表示状態が変わってルートとの間で交差の量の期待値を通るたびに、提供したコールバック関数が実行されます。

+通常、ターゲット要素の最も近いスクロール可能な祖先、またはターゲット要素がスクロール可能な要素の子孫でない場合は、端末のビューポートを基準にして交差の変化を監視したいと思うでしょう。端末のビューポートを基準にして交差を監視するには、 `root` オプションに `null` を指定します。交差オブザーバーのオプションについてのより詳しい説明は、このまま読み進めてください。 -

ターゲット要素とそのルート要素の交差する度合いが交差率です。これはターゲット要素のパーセンテージを 0.0 から 1.0 の間の値で表現したものです。

+ビューポートとその他の要素のどちらがルートとして使用されていても、 API は同じように動作し、ターゲット要素の表示状態が変わってルートとの間で交差の量の期待値を通るたびに、提供したコールバック関数が実行されます。 -

Intersection observer の作成

+ターゲット要素とそのルート要素の交差する度合いが**交差率**です。これはターゲット要素のパーセント値を 0.0 から 1.0 の間の値で表現したものです。 -

コンストラクターを呼び出して Intersection observer を作成し、閾値が一方向また他の方向に交差する度に実行されるコールバック関数を渡します。

+### 交差オブザーバーの作成 -
let options = {
+交差オブザーバーは、コンストラクターを呼び出して閾値が一方向また他の方向に交差する度に実行されるコールバック関数を渡すことで生成します。
+
+```js
+let options = {
   root: document.querySelector('#scrollArea'),
   rootMargin: '0px',
   threshold: 1.0
 }
 
-let observer = new IntersectionObserver(callback, options);
+let observer = new IntersectionObserver(callback, options); +``` -

1.0 の閾値は、 root オプションで指定された要素内でターゲットが100%表示された時にコールバックが呼び出されることを意味しています。

+閾値 (threshold) の 1.0 は、 `root` オプションで指定された要素内でターゲットが 100% 表示された時にコールバックが呼び出されることを意味しています。 -

Intersection observer のオプション

+#### 交差オブザーバーのオプション -

{{domxref("IntersectionObserver.IntersectionObserver", "IntersectionObserver()")}} コンストラクタに渡された options オブジェクトは、オブザーバーのコールバックが呼び出される状況を制御し、以下のフィールドがあります:

+`options` オブジェクトは {{domxref("IntersectionObserver.IntersectionObserver", "IntersectionObserver()")}} コンストラクターに渡され、オブザーバーのコールバックが呼び出される状況を制御します。以下のようなフィールドがあります。 -
-
root
-
ターゲットが見えるかどうかを確認するためのビューポートとして使用される要素です。指定されなかった場合、もしくは null の場合はデフォルトでブラウザーのビューポートが使用されます。
-
rootMargin
-
root の周りのマージンです。CSS {{cssxref("margin")}} プロパティに似た値を持つことができます。例えば、"10px 20px 30px 40px" (top, right, bottom, left) のようなものです。この値はパーセント値にすることができます。この一連の値は、交差を計算する前にルート要素の範囲のボックスの各辺を拡大または縮小させることができます。既定ではすべてゼロです。
-
threshold
-
単一の数値もしくは数値の配列で、オブザーバーのコールバックを実行するターゲットがどのくらいの割合で見えているかを示します。 50% 通過したときのみ検出する場合は値 0.5 を使用します。 25% を超える度にコールバックを実行する場合は、 [0, 0.25, 0.5, 0.75, 1] という配列を指定します。既定値は 0 です (つまり、1ピクセルでも表示されるとコールバックが実行されます)。1.0 の値は全てのピクセルが見えるようになるまで、閾値をまたいだとみなされないことを意味します。
-
+- `root` + - : ターゲットが見えるかどうかを確認するためのビューポートとして使用される要素です。指定されなかった場合、または `null` の場合は既定でブラウザーのビューポートが使用されます。 +- `rootMargin` + - : root の周りのマージンです。 CSS の {{cssxref("margin")}} プロパティに似た値を指定することができます。例えば、"`10px 20px 30px 40px"` (top, right, bottom, left) のようなものです。この値はパーセント値にすることができます。この一連の値は、交差を計算する前にルート要素の範囲のボックスの各辺を拡大または縮小させることができます。既定値はすべてゼロです。 +- `threshold` + - : 単一の数値または数値の配列で、ターゲットがどのくらいの割合で見えている場合にオブザーバーのコールバックを実行するかを示します。見える範囲が 50% を超えたときのみ検出する場合は値 0.5 を使用します。 25% を超える度にコールバックを実行する場合は、 \[0, 0.25, 0.5, 0.75, 1] という配列を指定します。既定値は 0 です(つまり、 1 ピクセルでも表示されるとコールバックが実行されます)。 1.0 の値は全てのピクセルが見えるようになるまで、閾値を超えたとはみなされないことを意味します。 -

監視される要素をターゲットにする

+#### 監視される要素をターゲットにする -

オブザーバーを作成した後は、監視するターゲット要素を与える必要があります。

+オブザーバーを作成した後は、監視するターゲット要素を与える必要があります。 -
var target = document.querySelector('#listItem');
+```js
+let target = document.querySelector('#listItem');
 observer.observe(target);
-
-

ターゲットが IntersectionObserver に指定された閾値を満たす度にコールバックが呼び出されます。コールバックは {{domxref("IntersectionObserverEntry")}} オブジェクトのリストとオブザーバーを受け取ります。

+// オブザーバーに設定したコールバックが初めて実行され、オブザーバーにターゲットが +// 割り当てられるまで待機します(ターゲットが現在表示されていない場合でも同様)。 +``` -
let callback = (entries, observer) => {
-  entries.forEach(entry => {
-    // Each entry describes an intersection change for one observed
-    // target element:
+ターゲットが `IntersectionObserver` に指定された閾値を満たす度にコールバックが呼び出されます。コールバックは {{domxref("IntersectionObserverEntry")}} オブジェクトのリストとオブザーバーを受け取ります。
+
+```js
+let callback = (entries, observer) => {
+  entries.forEach(entry => {
+    // それぞれのエントリーは、観測された 1 つの対象要素の交差状態の変化を示している。
     //   entry.boundingClientRect
     //   entry.intersectionRatio
     //   entry.intersectionRect
@@ -94,67 +99,71 @@ observer.observe(target);
     //   entry.time
   });
 };
-
+``` + +コールバックが受信したエントリーのリストには、交差状態の変化を報告した各ターゲットに対して 1 つのエントリーが含まれます。 {{domxref("IntersectionObserverEntry.isIntersecting", "isIntersecting")}} プロパティの値をチェックして、そのエントリーが現在ルートと交差している要素を表しているかどうかを確認します。 + +コールバックはメインスレッドで実行される点に注意してください。可能な限り早く動作する必要があります。もし時間を要する処理であるなら、 {{domxref("Window.requestIdleCallback()")}} を使ったほうがいいでしょう。 + +また `root` オプションを指定した場合、ターゲットはルート要素の子孫でなければなりません。 -

コールバックはメインスレッドで実行される点に注意してください。可能な限り早く動作する必要があります。もし時間を要する処理であるなら、 {{domxref("Window.requestIdleCallback()")}} を使ったほうがいいでしょう。

+### 交差の計算方法 -

また root オプションを指定した場合、target はルート要素の子要素でなければなりません。

+交差オブザーバー API によって考慮される領域はすべて矩形です。不規則に整形された要素は、要素全体を囲む最小の矩形で占有しているとみなされます。同様に、要素の可視部分が矩形ではない場合、要素が交差する矩形は要素の可視部分全体を含む最小の矩形であると解釈されます。 -

交差の計算方法

+{{domxref("IntersectionObserverEntry")}} オブジェクトによって提供される様々なプロパティがどのように交差を表現しているかを知るともっと役に立つでしょう。 -

Intersection Observer API によって考慮される領域は全て矩形です。不規則に整形された要素は、要素全てを囲む最小の矩形で占有しているとみなされます。同様に、要素の可視部分が矩形ではない場合、要素が交差する矩形は要素全ての可視部分を含む最小の矩形であると解釈されます。

+#### 交差するルートとルートマージン -

{{domxref("IntersectionObserverEntry")}} オブジェクトによって提供される様々なプロパティがどのように交差を表現しているかを知るともっと役に立つでしょう。

+ある要素とそのコンテナーとの交差を監視するまえに、まずはコンテナーを知る必要があります。ここでのコンテナーとは**交差ルート**または**ルート要素**です。これは監視される要素の親要素となる文書内の特定の要素になるか、文書のビューポートをコンテナーとして使用する際は `null` になるかいずれかになります。 -

交差するルートと root margin

+**ルート交差矩形**はターゲットをチェックするために使用される矩形です。この矩形は次のように決まります。 -

要素とその入れ物との交差を監視するには、入れ物をまずは知る必要があります。ここでの入れ物とは交差ルートもしくはルート要素です。これは監視される要素の親要素となる文書内の特定の要素になるか、文書のビューポートを入れ物として使用する際は null になるかいずれかになります。

+- 交差ルートが暗黙のルート(すなわち最上位の {{domxref("Document")}})である場合、ルート交差矩形はビューポートの矩形になります。 +- 交差ルートのあふれた部分が切り取られていた場合、ルート交差矩形はルート要素のコンテンツ領域になります。 +- それ以外の場合は、ルート交差矩形は交差ルートのクライアント矩形({{domxref("Element.getBoundingClientRect", "getBoundingClientRect()")}} を呼び出して返されるもの)です。 -

ルート交差矩形はターゲットをチェックするために使用される矩形です。この矩形は次のように決まります。

+交差するルートとして使用される矩形は、**ルートマージン** `rootMargin` を {{domxref("IntersectionObserver")}} の作成時に設定することで調整することが可能です。 `rootMargin` の値は交差するルートの境界ボックスの各辺にオフセットを追加定義して、最終的な交差のルートの境界を作成します(コールバックが実行された際には {{domxref("IntersectionObserverEntry.rootBounds")}} で取得できるものです)。 - +#### 閾値 -

交差するルートとして使用される矩形は、ルートマージン rootMargin を {{domxref("IntersectionObserver")}} の作成時に設定することで調整することが可能です。 rootMargin の値は交差するルートの境界線各辺にオフセット追加定義して、最終的な交差のルートの境界線を作成します (コールバックが実行された際には {{domxref("IntersectionObserverEntry.rootBounds")}} で取得できるものです)。

+交差オブザーバー API は、ターゲット要素が見える量の微細な変化が発生するたびに知らせるのではなく、**閾値** (threshold) を使用します。オブザーバーを作成する際に、表示されるターゲット要素がどの程度見えているかの割合を表す 1 つ以上の数値を指定できます。API はこれらの閾値を超えて見えたかどうかの変更のみを知らせます。 -

閾値

+例えば、ターゲット要素が 25% 見える度に通知を受けたい場合は、オブザーバーを作成する際に \[0, 0.25, 0.5, 0.75, 1] という配列を閾値のリストとして指定します。 -

Intersection Observer API はターゲット要素がどのくらい見えているのか微細な変化を全て知らせるのではなく、閾値 (thresholds) を使用します。オブザーバーを作成する際に、表示されるターゲット要素がどの程度見えているかのパーセンテージを表す1つ以上の数値を指定できます。API はこれらの閾値を超えて見えたかどうかの変更のみを知らせます。

+コールバックが呼び出されると、 `IntersectionObserverEntry` オブジェクトのリストを受け取ります。これは、ルートと交差する度合いが変化し、露出量がいずれかの方向に閾値を越えた観測対象ごとに 1 つずつあります。 -

例えば、ターゲット要素が25%見える度に通知を受けたい場合は、オブザーバーを作成する際の閾値のリストとして [0, 0.25, 0.5, 0.75, 1] という配列を指定します。変更の通知を受ける時にコールバック関数に渡された {{domxref("IntersectionObserverEntry")}} の {{domxref("IntersectionObserverEntry.isIntersecting", "isIntersecting")}} プロパティの値をチェックすることで、変更が感知された方向 (つまり要素が見えたかどうかを) 判断することが出来ます。isIntersectingtrue であれば、ターゲットは閾値を超えて少なくとも見るようになったということですし、false であればターゲットは指定した閾値では表示されなくなったということです。

+ターゲットが*現在*ルートと交差しているかどうかは、エントリーの {{domxref("IntersectionObserverEntry.isIntersecting", "isIntersecting")}} プロパティを見ることで確認できます。これにより、そのエントリーが、要素が交差している状態から交差しなくなるまでの遷移を表すのか、交差していない状態から交差する状態への遷移を表すのかを判断することができます。 -

閾値の仕組みを感じ取るには、下のボックスをスクロールして見てください。その中にある各色のボックスには四隅全てにパーセンテージが表示されています。そのため、入れ物をスクロールする時にこれらのパーセンテージが変化することが分かります。各ボックスには異なる閾値がセットされています:

+交差する矩形がゼロでないこともあり得ることに注意してください。これは、交差部分が両者の境界線にぴったり沿っているか、または {{domxref("IntersectionObserverEntry.boundingClientRect", "boundingClientRect")}} の面積がゼロの場合に起こり得ることです。このようにターゲットとルートが境界線を共有している状態は、交差した状態に遷移したとみなすには不十分です。 - +閾値の仕組みを感じ取るには、下のボックスをスクロールして見てください。その中にある各色のボックスには四隅全てにパーセント値が表示されています。コンテナーをスクロールする時にこれらのパーセント値が変化することが分かります。各ボックスには異なる閾値が設定されています。 - +``` -

{{EmbedLiveSample("Threshold_example", 500, 500)}}

+{{EmbedLiveSample("Thresholds", 500, 500)}} -

クリッピングと交差矩形

+#### クリッピングと交差矩形 -

ブラウザーは次のように最終的な交差矩形を計算します。これはすべて行われることですが、交差がいつ発生するかを正確に把握するために、これらの手順を理解すると役立ちます。

+ブラウザーは次のように最終的な交差矩形を計算します。これはすべて完了した後の状態が見えますが、交差がいつ発生するかを正確に把握するために、これらの手順を理解すると役立ちます。 -
    -
  1. ターゲット要素の境界矩形 (つまり、要素を構成するすべてのコンポーネントの境界ボックスを完全に囲む最小の矩形) は、ターゲットに対して {{domxref("Element.getBoundingClientRect", "getBoundingClientRect()")}} を呼び出すことによって取得されます。これは、交差する矩形の最大の大きさです。残りの手順では、交差しない部分を削除します。
  2. -
  3. ターゲットの直接の親ブロックから始まり、外側に向かって移動し、それぞれの包含ブロックのクリッピングが (存在すれば) 交差する長方形に適用されます。ブロックのクリッピングは、2つのブロックの交差と、 {{cssxref("overflow")}} プロパティで (存在すれば) 指定されたクリッピングモードに基づいて決定されます。 overflowvisible 以外を設定すると、クリッピングが行われます。
  4. -
  5. 包含する要素の1つがネストされた閲覧コンテキストのルートである場合 ({{HTMLElement("iframe")}} に含まれる文書など)、交差する矩形は含まれているコンテキストのビューポートで切り取られ、コンテナー群を通して上方に再帰的にコンテナーの包含ブロックを続けます。ですから、最上位の <iframe> に到達したら、交差矩形はフレームのビューポートに切り取られ、フレームの親要素が次のブロックとなり、交差ルートに向けて再帰が行われます。
  6. -
  7. 上方への再帰が交差ルートに達すると、結果の矩形が交差ルートの座標空間に対応付けられます。
  8. -
  9. 結果の矩形はそれからルート交差矩形と交差することで更新されます。
  10. -
  11. この矩形は、最終的に、ターゲットの {{domxref("document")}} の座標空間に対応付けられます。
  12. -
+1. ターゲット要素の境界矩形(つまり、要素を構成するすべてのコンポーネントの境界ボックスを完全に囲む最小の矩形)は、ターゲットに対して {{domxref("Element.getBoundingClientRect", "getBoundingClientRect()")}} を呼び出すことによって取得されます。これは、交差する矩形の最大の大きさです。残りの手順では、交差しない部分を削除します。 +2. ターゲットの直接の親ブロックから始まり、外側に向かって移動し、それぞれの包含ブロックのクリッピングが(存在すれば)交差する長方形に適用されます。ブロックのクリッピングは、 2 つのブロックの交差と、 {{cssxref("overflow")}} プロパティで(存在すれば)指定されたクリッピングモードに基づいて決定されます。 `overflow` に `visible` 以外を設定すると、クリッピングが行われます。 +3. 包含する要素の1つがネストされた閲覧コンテキストのルートである場合 ({{HTMLElement("iframe")}} に含まれる文書など)、交差する矩形は含まれているコンテキストのビューポートで切り取られ、コンテナー群を通して上方に再帰的にコンテナーの包含ブロックを続けます。ですから、最上位の `