CSS scroll-snap スクロールイベント停止と要素位置検出の実装

CSS scroll-snap スクロールイベント停止と要素位置検出の実装

1. スクロールスナップはフロントエンド開発者にとって必須のスキルです

CSS スクロール スナップは、Web ページ コンテナーがスクロールを停止したときに、JS コードを介さずにブラウザーが指定された要素の指定された位置に自動的かつスムーズに配置できるようにする非常に便利な機能です。スライドショー広告と同様の効果は、純粋な CSS で実現できます。

さらに、CSS Scroll Snap は互換性に優れており、モバイル デバイスでもほぼ安全に使用できます。

2. 実際のプロジェクトからのスクロールスナップシナリオ

今日の午後、機能要件を実装していたところ、Scroll Snap を使用して実装するのに非常に適したシナリオに遭遇しました。これは、スライドして文字を順番に表示するというものです。それで、大胆に使ってみたのですが、すごいですね。境界判定をするための js は必要なく、スライドが止まると自動的に目的の位置に配置されるんです。

主要な CSS コードは次のとおりです。

ul {
    幅: 375ピクセル; 高さ: 667ピクセル;
    scroll-snap-type: x 必須;
    -webkit-オーバーフロースクロール: タッチ;
    空白: ラップなし;
    オーバーフロー-y: 非表示;    
}
li {
    表示: インラインブロック;
    幅: 100%; 高さ: 100%;
    スクロールスナップ位置: 中央;
}

スクロールする親コンテナ要素scroll-snap-type:x mandatory設定し、水平方向にスクロールして配置を強制します。子リスト要素にscroll-snap-align:centerを設定すると、リストがスクロール コンテナの中央に表示されるため、効果が得られます。

ただし、スクロール配置が完了した後も、現在配置されている文字素材を強調表示する必要があります。これはちょっと難しかったです!

従来、このスライド効果は JS を使用して実装されていました。JS アニメーションが終了しても、CSS アニメーションが終了しても、使用できるコールバック関数がありました。しかし、ここでは転がっており、転がった後、しばらくは自己位置を決めます。自己位置を決める時間はさまざまです。いつ止まるかは誰にもわかりません。複数の要素を一度にスライドすると、どの要素で停止すればよいかわからない場合があります。

実際、標準設定者とブラウザメーカーは、スクロールがいつ停止するか、どの要素にスクロールが位置しているかを正確に把握できるように、スクロールスナップ関連のコールバックイベントの実装を積極的に推進しています。ただし、この標準はまだ開発中であり、ブラウザはまだこれをサポートしていません。プロジェクトを今すぐ使用する必要があります。どうすればよいでしょうか?

右! JS アシスタンスを使用する必要があります。

実際、Scroll Snap の使用シナリオでなくても、通常のスクロールであっても、スクロールの慣性により、スクロールが停止したかどうかを検出することも一般的な要件です。そのため、スクロールが停止したことを検出する方法を考え出す必要があります。

3. スクロール停止検出方法

要素のスクロールが停止したかどうかを検出するための実装アイデアは、スクロール イベントでタイマーを実行して、現在のスクロール距離が前回のスクロールの距離と等しいかどうかを記録することです。等しい場合は、スクロールが停止したと見なされます。等しくない場合は、スクロールがまだ進行中であると見なされます。

JavaScript 表現は次のとおりです (この実装は非推奨です)。

// 水平スクロールが終了したかどうかを検出するために使用されるタイマー var timer = null;
// 最後のスクロール距離 var scrollLeft = 0, scrollTop = 0;
// スクロールイベントが開始されます。container.addEventListener('scroll', function () {
    タイマーの間隔をクリアします。
    // タイマーをリセットする timer = setInterval(function () {
        コンテナのスクロール左 == スクロール左 && コンテナのスクロール上 == スクロール上) {
            // スクロール距離が等しい場合、スクロールが停止したとみなします clearInterval(timer);
            // ... コールバック処理など、必要な処理を実行します } else {
            // それ以外の場合は、最後のスクロール位置を記憶します scrollLeft = container.scrollLeft;
            スクロールトップ = コンテナ.スクロールトップ;
        }
    }, 100);
});

興味があれば、上記のコードをさらにカプセル化することもできます。

翌日更新

慣性スクロール イベントとスナップ位置スクロール イベントの両方が継続的にトリガーされるため、スクロール終了検出では、前のスクロール距離と次のスクロール距離が等しいかどうかを判断する必要はありません。したがって、直接的に次のことが可能です。

// 水平スクロールが終了したかどうかを検出するために使用されるタイマー var timer = null;
// スクロールイベントが開始されます。container.addEventListener('scroll', function () {
    タイマーをクリアします。
    // タイマーをリセットする timer = setTimeout(function () {
        // スクロール イベントがトリガーされないため、スクロールは停止したとみなされます // ... コールバック処理など、必要な処理を実行します }, 100);
});

もちろん、上記で提供した方法は、ブラウザ自体にスクロールスナップの最終的な再配置の検出機能があるため、非常に正確な終了検出ではありません。私が何度も調査とテストを行った結果、この検出イベントは350ms (実際の動作は数ミリ秒程度長くなる可能性があります)である必要があり、これは上記で設定した100msよりもはるかに大きいです。そのため、スナップ配置が開始される前に、誤った冗長な判断が行われることになります。

考えてみると、この問題は避けられないが、大きな問題ではないことに気づきました。検出時間を400msに設定することはできません。遅延が大きすぎて、エクスペリエンスが良くない可能性があります。

4. 現在のスクロール対象要素の検出方法

原理は次のとおりです。すべてのリスト要素を反復処理し、スクロール コンテナーの左端 (左揃えの場合 - scroll-snap-align:left )、中央 (中央揃え)、または右端 (右揃え) を基準としたリスト要素の左端の位置を検出します。もちろん、リスト要素のサイズがスクロール コンテナーのサイズと一致している場合は、左、中央、右のエッジ検出のいずれも許容されます。

JS は以下を示します:

[].slice.call(container.children).forEach(関数(ele, インデックス) {
    (Math.abs(ele.getBoundingClientRect().left - container.getBoundingClientRect().left) < 10) の場合 {
        // 現時点での ele 要素は現在配置されている要素です // ... ele で好きなことをすることができます } else {
        // 現時点での ele 要素は現在配置されている要素ではありません}
});

厳密に言えば、 10未満ではなく0に等しいかどうかを計算する必要があります。ここで、許容区間を追加します。

JS の支援を必要とする上記の 2 つの要件を解決すると、最終的な効果が達成されます。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

<<:  1 行または複数行のテキストがオーバーフローしたときに省略記号を表示する CSS を実装する方法

>>:  HTML マーキー文字フラグメントのスクロール

推薦する

Linux のよく使うコマンドの使い方を詳しく解説(第 2 回)———— テキストエディタのコマンド vi/vim

vi/vim の紹介どちらもマルチモード エディターです。違いは、vim が vi のアップグレー...

MySQL のストレージ エンジンの違いと比較

MyISAM ストレージエンジンMyISAM は ISAM ストレージ エンジンに基づいており、それ...

Linux マルチスレッドにおけるフォークとミューテックス ロック プロセスの例

目次質問: 1. 最初の試み2. 合理的な分析3. 問題解決(1) pthread_join()の使...

Windows 10にWSL2 Ubuntu20.04をインストールしてdocker環境を構築する方法

WSLを有効にするシステムがWindows 10 2004以降であることを確認してください 「メニュ...

Pycharmとsshリモートアクセスサーバーdockerの詳細なチュートリアル

背景: 一部の実験はサーバー上で完了する必要があります。したがって、リモート サーバー上のコードをロ...

Docker での FastAPI デプロイの詳細なプロセス

Docker 学習https://www.cnblogs.com/poloyy/p/15257059...

MySQL データベースの Binlog 使用法の概要 (必読)

MySQL データベースにとって binlog バイナリ ログがどれほど重要であるかについては詳し...

Linux での MySQL 5.7.18 バイナリ パッケージのインストール チュートリアル (デフォルトの構成ファイル my_default.cnf なし)

現在、MySQL を学習中です。私は完全な初心者で、Linux についてはあまり知りません。今後の作...

Docker 経由で wsl の tar ファイルを作成する方法

最近VScodeのリモート開発機能をいじっています。Dockerのコンテナに接続できるほか、WSLに...

Nginx がリクエストを処理する際のマッチングルールの詳細な分析

nginx はリクエストを受信すると、まず server_name でサーバーを照合し、次にサーバー...

Linux ディスクのマウント、パーティション分割、容量拡張操作を実装する方法

基本概念操作の前に、まずいくつかの基本的な概念を理解する必要がありますディスクLinux システムで...

コンピュータが予期せずシャットダウンした後、VMware で Linux がインターネットに接続できない問題の解決策

問題の説明: Linux システムのネットワーク カード ファイル /etc/sysconfig/n...

docker-composeの詳細なインストールと使用方法

Docker Compose は、複雑なアプリケーションを定義および実行するための Docker ツ...

jQuery タグセレクターの適用例の詳細な説明

この記事では、jQueryタグセレクターアプリケーションの具体的なコードを例として紹介します。具体的...

nginx 503 サービスが一時的に利用できない問題を解決する方法

最近、ウェブサイトを更新すると、503 Service Temporarily Unavailabl...