JavaScriptでもスナップスクロール。

〽️ PCでも快適に。


PCでタップ操作はキツい。

こんにちは、「ふ」です。
以前、 CSSを使ったスナップスクロール を紹介しましたが、

上のインターフェースを操作してみてください。

今このページを訪問してくださった(有難うです!)あなたは、スマホですか? だとしたら快適にスナップスクロールが味わえると思います。

一方。PCで観てもらっている方(有難うです!)。マウスでスクロールバーをつかんでから、ドラッグして次の画像を観る。・・とてももどかしい思いをさせてしまっていると思います。

CSSでの水平スクロール

◼︎ モバイル環境では快適。

◼︎ PCではマウス操作でスクロールしなければならないので、もどかしい事この上なし。直帰確実。

というわけで、PCで訪問してくださった方のために、「ボタンをクリックする事で要素をスナップスクロールさせる」UIを実装してみたいと思います。CSSではなくJavaScriptを使います。



UI作り。



3枚の画像が横にスクロールすることで順に登場する部分と、その下に「◀︎」「▶︎」ボタンをテキトーに作って配置します。
横スクロールの実装方法については こちら

HTML

「「3//横スクロール部分。3枚の画像を配置」」
「「3//ボタンエリア。」」
<button id ="modoru" type = "button" 「「1onclick = "modoru()"」」> ◀︎ </button> <button id = "susumu" type = "button" 「「1onclick = "susumu()"」」> ▶︎ </button>

buttonには「onclick」で関数が実行されるように仕込んでおきます。

・親要素の識別子は「id」で設けたほうが、JavaScriptで参照する際に複雑にならないので便利です。

CSS

#jsnap { width:100%; display:flex; 「「1//タッチ操作などでスクロールできないようにする。」」 overflow-x:hidden; } #jsnap > div { height:100%; width:100%; flex:none; display:flex; align-items:center; justify-content:center; } #jsnap > div > img { width:50%; padding-left:0; } 「「3//buttonを左右に振り分け。」」 #modoru{ float:left; } #susumu{ float:right; } 「「3//ボタンエリアの幅、センタリングなど」」 #buttons { display:block; margin:0 auto; width:50%; }



横スクロール部分の親要素のCSSについてですが、この部分をタッチ操作でスクロールできてしまうとこのあと記述するJavaScriptでうまく動作しません。「overflow:hidden」でタッチ操作を無効にしておきます。

以上、UIが準備できたところで、



作戦会議。

どのようにJavaScriptを実装していくか、作戦を立てていきましょう。

以下Js。


var element = document.getElementById("jsnap");

まづは変数「element」として親要素を取得。

console.log(element.children); 「「1▶︎ HTMLCollection(3)[div,div,div]」」

element.childrenで子要素のHTMLCollectionが取得できます。
これは配列のように操作が可能で、個別の子要素をelement.children[n]で取得することができ、子要素の数はelement.children.lengthで取得できます。

var num = 0;

var numを宣言。この値を増減させることで、取得する子要素を切り替え、そこにスクロールさせるという作戦です。

element.children[num].scrollIntoView ( { behavior:"smooth", block:"nearest", inline:"nearest", } );

スナップスクロールをJavaScriptで行うためには、scrollIntoView()メソッドを使用します。これを実行すると、指定した要素がウィンドウ上の表示範囲に入るまでページがスクロールされます。

そのパラメータとして、behavior:"smooth"と指定することでスムーススクロール(画面が急に切り替わるのではなく、スクロールアニメーションを伴って切り替わる)が実装できます。

2019年8月現在、scrollIntoViewのbehavior:smoothはsafariではうまく動きません。
対応していないのか、ベンダープレフィックスが必要なのか・・調査中です。

そのあとに記述されている、「block」と「inline」。これは縦/横方向のスクロール位置を指定するパラメータになります。いずれも「nearest」(現在の表示位置から近い方にスクロールさせる)に設定しておきましょう。

以上を踏まえて・・・・・



実装していきましょう。

scriptを書いていきます。まづグローバル部分にて親要素の取得、子要素参照のための変数「num」を定義します。

「「1//親要素取得」」 var element = document.getElementById("jsnap"); 「「1//子要素を参照するための番号」」 var num = 0;

「susumu]関数。現在表示されている子要素の次の要素が存在する場合、すなはち「num+1」がelement.childrenの要素数よりも少ない時に次の要素「child」にスクロール。

そうでなければreturnで何も起こらない。
「num」はインクリメントされて次回はそのまた次の要素を取得できるようにする。

function susumu() { if(num+1 < element.children.length) { var child = element.children[num+1]; child.scrollIntoView( { behavior:"smooth", block:"nearest", inline:"nearest", } ); num++; } else { return; } }

「modoru」関数。現在表示されている子要素の前の要素が存在する、「num-1」が0以上の場合に前の要素「child」にスクロール。

同じく条件を満たさなければreturn。
「num」はデクリメント、そのまた前にある要素を取得できるようにする。

function modoru() { if(num-1 >= 0) { var child = element.children[num-1]; child.scrollIntoView( { behavior:"smooth", block:"nearest", inline:"nearest", } ); num--; } else { return; } }

scriptは以上です。ビルドしてみましょう!



完成です。

実際に動かしてみてください。






タッチ操作のできないPC上でもこのUIであればユーザもわかりやすく、ストレスなく閲覧できそうです。

こうなると「現在何番目の要素が表示されているか」が視認できるようなインジゲーターも配置してみたくなりました。そしてメディアクエリでモバイル/PCのUIを切り替えられるようにしたい。

やってみたい事がどんどん増えてきて忙しい♪
また開発に成功したら「フーノページ」で紹介したいと思います。













「ふ」です。

swift、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。

🐧 twitter 🐧