タイムアウト関数を削除してバグを解消しましょう。本当に必要なイベントは scrollend です。
scrollend イベントの前は、スクロールが完了したことを検出する信頼できる方法がありませんでした。そのため、イベントが遅れて発生したり、ユーザーの指がまだ画面に触れている間に発生したりしていました。スクロールが実際に終了したタイミングを把握できないというこの不確実性は、バグやユーザー エクスペリエンスの低下につながっていました。
document.onscroll = event => { clearTimeout(window.scrollEndTimer) window.scrollEndTimer = setTimeout(callback, 100) }
この setTimeout() 戦略でできる最善のことは、100ms でスクロールが停止したかどうかを把握することです。これにより、スクロール終了イベントではなく、スクロール一時停止イベントのように動作します。
scrollend イベントの後、ブラウザはこうした複雑な評価をすべて行います。
document.onscrollend = event => {…}
いい材料だ。出力前に、適切なタイミングで、意味のある条件をすべて満たします。
試してみる
イベントの詳細
scrollend イベントは、次の場合に発生します。
- ブラウザがスクロールのアニメーションや変換を停止した。- ユーザーがタップを離した。
- ユーザーのポインタがスクロールバーのつまみを離した。
- ユーザーのキープレスがリリースされました。
- フラグメントへのスクロールが完了しました。
- スクロール スナップが完了しました。
- scrollTo() が完了しました。
- ユーザーがビジュアル ビューポートをスクロールした。
scrollend イベントは、次の場合には発生しません。
- ユーザーの操作によってスクロール位置が変更されなかった(移動が発生しなかった)。
- scrollTo() の翻訳結果がありませんでした。
このイベントがウェブ プラットフォームに導入されるまでに時間がかかったのは、仕様の詳細が必要な小さな詳細が多数あったためです。最も複雑な領域の 1 つは、ドキュメントに対するビジュアル ビューポートの scrollend の詳細を明確にすることでした。ズームインしたウェブページを考えてみましょう。このズーム状態では、スクロールしてもドキュメントがスクロールされるとは限りません。このビジュアル ビューポートのユーザー主導のスクロール操作でも、完了すると scrollend イベントが発行されます。
イベントの使用
他のスクロール イベントと同様に、リスナーを登録する方法はいくつかあります。
addEventListener("scrollend",> (event) = {
// scroll ended
});
aScrollingElement.addEventListener("scroll>end", (event) = {
// scroll ended
});
または、イベント プロパティを使用します。
document.onscrollend = (event) => {
// scroll ended
};
aScrollingElement.onscrollend = (event) => {
// scroll ended
};
ポリフィルとプログレッシブ エンハンスメント
この新しいイベントを今すぐ使用する場合は、次のアドバイスを参考にしてください。現在のスクロール終了戦略(ある場合)を引き続き使用し、その開始時に次の方法でサポートを確認できます。
'onscrollend' in window
// true, if available
ブラウザがイベントを提供しているかどうかに応じて、true または false が報告されます。このチェックにより、コードを分岐できます。
if ('onscrollend' in window) {
document.onscrollend = callback
}
else {
document.onscroll => event = {
clearTimeout(window.scrollEndTimer)
window.scrollEndTimer = setTimeout(callback, 100)
}
}
これは、scrollend イベントが利用可能になったときに、プログレッシブ エンハンスメントを行うための健全なスタートです。また、ブラウザで可能な限り動作するように作成したポリフィル(NPM)を試すこともできます。
import {scrollend} from "scrollyfills"
// then use scrollend as if it's existed this whole time
document.onscrollend = callback
ポリフィルは、ブラウザに組み込まれた scrollend イベントが利用可能な場合は、それを使用するようにプログレッシブ エンハンスメントを行います。利用できない場合、スクリプトはポインタイベントとスクロールを監視して、イベントの終了を可能な限り正確に推定します。
ユースケース
スクロール中は、計算負荷の高い処理を避けることをおすすめします。この方法により、スクロールは、スムーズなエクスペリエンスを維持するために必要なメモリと処理を自由に使用できます。scrollend イベントを使用すると、スクロールが停止するため、コールアウトして負荷の高い処理を行うのに最適なタイミングが得られます。
scrollend イベントは、さまざまなアクションをトリガーするために使用できます。一般的なユースケースは、関連する UI 要素をスクロールが停止した位置と同期することです。例:
- カルーセルのスクロール位置をドット インジケーターと同期する。
- ギャラリー アイテムとそのメタデータの同期。
- ユーザーが新しいタブにスクロールした後にデータを取得する。
たとえば、ユーザーがメールをスワイプして消すシナリオを考えてみましょう。スワイプが終了したら、スクロールした場所に基づいてアクションを実行できます。
このイベントは、プログラムによるスクロールやユーザーによるスクロール、ログ分析などのアクションの後に同期するために使用することもできます。
スクロール位置に基づいて、矢印、ドット、フォーカスなどの複数の要素を更新する必要がある場合の適切な例を次に示します。このカルーセルの作成方法を YouTube でご覧ください。ライブデモもお試しください。
この機能のエンジニアリング作業を担当した Mehdi Kazemi 氏と、API と実装のガイダンスを提供した Robert Flack 氏に感謝いたします。