カスタム スクロールバーはめったにありません。ほとんどの場合、 スクロールバーは 編集不可(日付選択ツール)です。 JavaScript を使用して独自に作成することもできますが、それには費用がかかり、 遅延を感じる場合がありますこの記事では、 型にはまらない CSS マトリックスを使用して、カスタム スクローラーを作成します。 スクロール中に JavaScript を生成します。
要約
小さなことは気にしないでしょ?必要なのは にんちゃんのデモ 図書館を手に入れるの?デモのコードは GitHub リポジトリ。
LAM;WRA(Long と数学的、いずれにせよ読み上げられる)
以前、Google はパララックス スクローラーを開発しました。 該当する記事をご覧ください。 時間をかける価値は十分にあります)。CSS 3D を使用して要素をプッシュバックする 要素が実際のスクロール速度より遅く移動しました。
内容のまとめ
まず、パララックス スクローラーの仕組みを復習しましょう。
アニメーションに示すように、要素をプッシュすることで視差効果を実現しています。 3D 空間の Z 軸に沿った「後方」ドキュメントをスクロールすると、 Y 軸に沿った平行移動が表示されますたとえば 100 ピクセル分だけ下にスクロールした場合、 要素は 100 ピクセル上方向に翻訳されます。これはすべての要素に当てはまりますが、 「さらに後戻り」のジョブでもかまいませんしかしなぜ彼らは 観測された画面上の動きが 100 ピクセル未満であることから、 目的の視差効果を適用します。
もちろん要素を空間に戻すと小さくなりますが 要素をスケールアップして修正します。正しい計算方法を見つけました Google が開発した パララックス スクローラー 詳しい説明は省きますが
ステップ 0: 何をしたいのか?
スクロールバー。私たちが構築するのは、これだけです。データ アナリストが 業務内容についてですもちろんです。スクロールバーは 利用可能なコンテンツの進捗度と進捗度 考えなければなりません下にスクロールすると、スクロールバーが 最終段階に近づいていることを示すことができます。すべての内容が スクロールバーは通常は非表示になります コンテンツの高さがビューポートの 2 倍の場合、 スクロールバーがビューポートの高さの 2 分の 1 まで表示されます。高さの 3 倍のコンテンツ ビューポートがスクロールバーをビューポートの 3 分の 1 などに拡大縮小します。 スクロールする代わりに、スクロールバーをクリックしてドラッグし、 サイトをより迅速に提供できます目立たない人にとっては 目立たない人にとっては といった要素です。一つずつ戦いましょう。
ステップ 1: 逆に並べる
CSS 3D を使用すると、要素の移動速度をスクロール速度より遅くすることができます 視差スクロールの記事で概説されているように、逆に、元のバージョンを 方向性は?それが可能なこと、そしてそれが フレームにぴったりなカスタム スクロールバーです。この仕組みを理解するには まずは CSS 3D の基本から説明します。
数学的な視点から見た投影法は、 最終的には 同種座標。 その機能とその理由については詳しく説明しませんが、 w という 4 つ目の座標が追加された 3D 座標のようなものです。この 座標は、視点の歪みを持たせる場合を除き、1 にする必要があります。水 ここでは何も使用しないため、w の詳細は気にする必要はありません。 指定することもできます。したがって、すべての点はこれから 4 次元ベクトルになります。 [x, y, z, w=1] なので、行列は 4x4 にします
ある例として、CSS では
フードは、
matrix3d()
関数を使用します。matrix3d
は 16 個の引数を取ります(行列が
4x4 など)を使用して、列を次々と指定します。この関数を使用して
回転や翻訳などを手動で指定できますが
その w 座標がおかしいということです。
matrix3d()
を使用する前に、3D コンテキストが必要です。これは、
3D コンテキストでは遠近感の歪みはなく、
同次座標系が作成されます。3D コンテキストを作成するには、
perspective
と、その内部で新しく変換できる要素
作成しました。対象
例:
Perspect コンテナ内の要素が CSS エンジンによって処理される 次のとおりです。
- 要素の各角(頂点)を同次座標系に変換する
[x,y,z,w]
(パースペクティブ コンテナを基準とする) - 要素のすべての変換を右から左に行列として適用します。
- 視点要素がスクロール可能な場合は、スクロール マトリックスを適用します。
- 遠近感マトリックスを適用します。
スクロール マトリックスは y 軸に沿った変換です。下にスクロールすると、 400 ピクセルの場合は、すべての要素を 400 ピクセル分上に移動する必要があります。パースペクティブ マトリックスは 点を 3 次元で消失点の近くに「引っ張る」行列 できます。このようにすると、小さくなったときに 逆方向になり、翻訳する際に「動きが遅くなります」。 そのため、要素がプッシュバックされた場合、400 ピクセルの移動により要素が 画面上で 300px だけ移動します
詳細は、 CSS の仕様 概要を示していますが、この記事では説明のため、簡略化して アルゴリズムです。
ボックスは、perspective
の値が p の視点コンテナ内にあります。
コンテナがスクロール可能で、
n ピクセル。
1 つ目の行列は視点行列、2 つ目の行列はスクロールです 表します。まとめると、スクロール マトリックスの役割は、スクロール アクションによって要素が上に移動することです。 下にスクロールするため、負の符号が付けられます。
一方、スクロールバーでは反対の要素、つまり
下方向にスクロールする下。ここで、
ボックスの角の w 座標を反転します。w 座標が
-1 の場合、すべての翻訳が反対の方向に有効になります。どのように
?CSS エンジンがボックスの角を
w を 1 に設定します。matrix3d()
が輝くときがやってきました!
.box {
transform:
matrix3d(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, -1
);
}
この行列は w を否定するだけです。CSS エンジンが
各隅を [x,y,z,1]
形式のベクトルに変換すると、行列は
[x,y,z,-1]
に変換します。
要素変換の効果を示す中間ステップをリストしました。 表します。行列の計算が苦手な場合でも問題ありません。ユーレカ号 最後の行では、スクロールオフセット n を y の値に 座標の差を求めるためです。要素は下方向へ翻訳されます 下にスクロールします。
しかし、このマトリックスをモデルに 例 要素は表示されません。これは、CSS の仕様で、すべての Pod に w < である頂点0 は要素のレンダリングをブロックします。Z は 座標が現在 0、p が 1 の場合、w は -1 になります。
幸い、z の値を選択できます。w=1 にするには、次が必要です。 z = -2 に設定します。
.box {
transform:
matrix3d(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, -1
)
translateZ(-2px);
}
見よ、私たちの box が戻ってきた!
ステップ 2: 移動する
今のこの箱はこうして出来上がっています 学びます現時点では、視点コンテナはスクロールできないため、 要素は見えても要素が逆向きになることがわかっています スクロールしました。では、コンテナをスクロールしてみましょう。追加することもできます。 スペースを占有するスペーサー要素:
<div class="container">
<div class="box"></div>
<span class="spacer"></span>
</div>
<style>
/* … all the styles from the previous example … */
.container {
overflow: scroll;
}
.spacer {
display: block;
height: 500px;
}
</style>
次に ボックスをスクロールしてください。 赤いボックスが下に移動します。
ステップ 3: サイズを指定する
ページを下にスクロールすると下に移動する要素があります。これこそが 手間がかかります次はスクロールバーのように見えるように スタイルを設定し インタラクティブにできます。
スクロールバーは通常、「つまみ」と「トラック」で構成されますが、トラックは「トラック」ではありません 表示されます。親指の高さは 表示されます。
<script>
const scroller = document.querySelector('.container');
const thumb = document.querySelector('.box');
const scrollerHeight = scroller.getBoundingClientRect().height;
thumb.style.height = /* ??? */;
</script>
scrollerHeight
はスクロール可能な要素の高さで、
scroller.scrollHeight
は、スクロール可能なコンテンツの高さの合計です。
scrollerHeight/scroller.scrollHeight
は、コンテンツに対する次の割合です。
表示されます。つまみカバーの縦方向のスペースの比率は、
表示されるコンテンツの割合:
<script>
// …
thumb.style.height =
scrollerHeight * scrollerHeight / scroller.scrollHeight + 'px';
// Accommodate for native scrollbars
thumb.style.right =
(scroller.clientWidth - scroller.getBoundingClientRect().width) + 'px';
</script>
親指の太さは いい感じ、 進化のスピードが速すぎますここで 高度な分析手法から パララックス スクローラーです。要素をさらに戻ると、移動が遅くなり、 使用できます。サイズを修正するには、スケールアップします。ただし、 どうすれば復元できるでしょうか。ご想像のとおり、計算をしてみましょう。今回が最後です。 あります。
重要なのは、親指の下端を
スクロール可能な要素を下端までスクロールしたときに、下端に揃えられる
できます。つまり、スクロールした場合、
scroller.scrollHeight - scroller.height
ピクセルの場合、親指を
scroller.height - thumb.height
に翻訳されました。スクローラーのピクセルごとに、
次のようにして、親指を 1 ピクセル動かすことができます。
これがスケーリング ファクタです。次に、スケーリング ファクタを
視差スクロールですでに行った Z 軸に沿った平行移動
の記事を参照してください。「
仕様の関連セクション:
スケーリング ファクタは p/(p - z) と等しくなります。この方程式を z について解くと、
親指を z 軸にどの程度平行移動させるかを考えてみましょう。でも、
w 座標の乱用により、1 次元の座標を 1 次元に
z 方向にある追加の -2px
。また、要素の変換は複数の要素に適用され、
右から左に表記する必要があります
この特別なマトリックスより前には
ただし、この特別なマトリックスより後の翻訳はすべて反転します。では、
体系化してください。
<script>
// ... code from above...
const factor =
(scrollerHeight - thumbHeight)/(scroller.scrollHeight - scrollerHeight);
thumb.style.transform = `
matrix3d(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, -1
)
scale(${1/factor})
translateZ(${1 - 1/factor}px)
translateZ(-2px)
`;
</script>
Google には、 scrollbar! そしてこれは DOM 要素にすぎません。自由にスタイルを設定できる要素です。一つは、 アクセシビリティに関して重要なのは、親指を 多くのユーザーはこの方法でスクロールバーを操作できるため、 このブログ投稿を長くするため、ここでは説明は その部分の詳細が表示されます。詳しくは、 ライブラリ コード をご覧ください。
iOS についてはどうですか?
旧友の iOS Safari だ。パララックススクロールと同様に
見てみましょう。要素上をスクロールしているため、
-webkit-overflow-scrolling: touch
します。ただし、その場合は 3D のフラット化と
スクロール効果が機能しなくなりますこの問題はパララックス スクローラーで解決されました
iOS Safari を検出し、回避策として position: sticky
を使用する
ここではまったく同じことをします。詳しくは、
パララックス記事
思い出してください。
ブラウザのスクロールバーについてはどうですか?
システムによっては、永続的なネイティブ スクロールバーの処理が必要になります。
これまでは、スクロールバーを非表示にすることはできませんでした(ただし、
非標準疑似セレクタ)。
隠すには、(数学のない)ハッキングに頼る必要があります。Google は
overflow-x: hidden
を使用してコンテナ内のスクロール要素を作成し、
スクロール要素の幅がコンテナより広くなります。ブラウザのネイティブのスクロールバーは
非表示になります。
Fin
これらをまとめると、フレームに最適なカスタム スクロールバーを ニャン猫のデモ。
にんちゃんが見えない場合は、 報告したバグが (親指をクリックして Nyan 猫が表示される) Chrome は不要な作業を避けるのが得意です 画面に表示されないものを描画したり アニメーション化したりできます残念ながら マトリックスの不正プログラムにより、ねこに猫の GIF が実際に画面に表示されないようになっている。 この問題が早急に解決されることを願っております。
これで準備は完了です。これは大変な作業でした。最後まで読んでくれたことを感謝します あります。これは、 手間がかかるので 労力に見合う価値は ほとんどありませんが ただし、カスタマイズされたスクロールバーがエクスペリエンスに不可欠な要素である場合は除きます。しかし、 可能だとわかってよかったです。これほど難しいのは カスタム スクロールバーは、CSS 側で行うべき作業があることを示します。でも大丈夫! 将来的には Houdini の AnimationWorklet は、 スクロールに連動してフレームに完全に収まる効果を出す方がはるかに簡単です。