タイムアウト関数を削除し、バグを取り除きます。本当に必要なイベントは、scrollend です。
scrollend
イベントが発生する前は、スクロールが完了したことを信頼できる方法で検出できませんでした。つまり、イベントの呼び出しが遅くなったり、ユーザーの指が画面下に置いたままになったりしていました。スクロールが実際に終了したタイミングを把握することは難しいため、バグが発生し、ユーザー エクスペリエンスが低下していました。
document.onscroll = event => { clearTimeout(window.scrollEndTimer) window.scrollEndTimer = setTimeout(callback, 100) }
この setTimeout()
戦略でできることは、スクロールが 100ms
停止しているかどうかを確認することです。これは、スクロールが終了イベントではなく、スクロールの一時停止イベントのようなものです。
このような難しい評価は、scrollend
イベントの後にブラウザによって自動的に行われます。
document.onscrollend = event => {…}
そういうものだよね。完全にタイミングよく指定され、意味のある条件が満載された状態で出力されます。
試してみる
イベントの詳細
scrollend
イベントは、次の場合に発生します。
- ブラウザがスクロールのアニメーション化または翻訳を停止した場合。
- ユーザーのタップが離された。
- ユーザーのポインタによってスクロールつまみが離された。
- ユーザーのキー操作が解除されました。
- 「フラグメントまでスクロール」完了。
- スクロールのスナップが完了しました。
- scrollTo()
が完了しました。
- ユーザーがビジュアル ビューポートをスクロールした。
scrollend
イベントは、次の場合は呼び出されません。
- ユーザーの操作によってスクロール位置が変化しなかった(変換が行われなかった)。
- scrollTo()
では翻訳されませんでした。
このイベントがウェブ プラットフォームに導入されるまでに時間がかかったのは、仕様の詳細を必要とする多くの細かな詳細情報が原因です。最も複雑な領域の一つは、ドキュメントに対してビジュアル ビューポートの scrollend
の詳細を明確にすることでした。ズームインしているウェブページを考えてみましょう。このズーム状態ではスクロールが可能であり、必ずしもドキュメントがスクロールされるわけではありません。このようなビジュアル ビューポートのユーザー操作によるスクロール操作でも、完了すると scrollend
イベントが出力されます。
イベントの使用
他のスクロール イベントと同様に、リスナーはいくつかの方法で登録できます。
addEventListener("scrollend", (event) => {
// scroll ended
});
aScrollingElement.addEventListener("scrollend", (event) => {
// scroll ended
});
または、event プロパティを使用します。
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
イベントが利用可能になり次第、段階的に機能強化を行うことが可能となります。また、ブラウザに最適なpolyfill(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 に感謝します。