jQueryを使わずにマウスドラッグスクロールを実装する
中学生の時に趣味でZ80マシン語やFortran等を始めてから、現在まで数多くのプログラミング言語を経験。ShopifyによるECサイト構築では主にカスタマイズを担当。
はじめに
初めに断っておきますが、私はjQuery否定派では決してありません。
DOMから取得したオブジェクトがHTMLCollectionなのかNodeListなのかElementなのかとかをいちいち気にする必要がなくなる上に、jQueryオブジェクトのメソッドは強力で、アニメーションが簡単に実装でき、CSSも簡単に操作でき、そして記述が劇的に短くなりコードがとても見やすくなったりします。
しかしカスタマイズの仕事をしていると、jQueryライブラリが読み込まれていないページをカスタマイズしなければならない場面が多々発生します。
ECサイトは「表示速度が0.1秒遅くなると売上が1%減少する」とか「表示速度が1秒から3秒に落ちると、直帰率は32%上昇する」とか言われている世界です。
また、表示速度が遅いとユーザビリティが悪いとみなされて、検索順位が下がる可能性も高くなります。
その様な理由から、ちょっとしたカスタマイズだけのためだけにjQueryライブラリを読み込むのには躊躇してしまいます。
この記事ではちょっとしたカスタマイズをバニラなJavaScriptでカスタマイズする例をご紹介します。
マウスドラッグスクロールをテストする
商品詳細ページの商品画像サムネイル表示とかでよくあるのですが、親要素のCSSでoverflowにautoが指定されていて、なおかつその中身の要素が大きい時は、スクロールバーが表示されます。
スマートフォンやタブレットの時はドラッグでスクロールできるのですが、PCの場合はマウスをドラッグしても動きません。これをPCでもマウスでドラッグスクロールできるようにします。
まずは、サンプルのHTMLとCSSの準備です。
<div class="wrap"> <div class="inner inner1">aaa</div> </div> <div class="wrap"> <div class="inner inner2">bbb</div> </div> <div class="wrap"> <div class="inner inner3">ccc</div> </div> <style> .wrap { display: inline-block; margin-right: 30px; width: 200px; height: 100px; overflow: scroll; margin-bottom: 30px; cursor: pointer; } .inner { width: 500px; height: 500px; } .inner1 { background-image: repeating-radial-gradient(circle at 30% 72%, rgba(178, 254, 255, 1), rgba(137, 219, 248, 1) 12%, rgba(178, 254, 255, 1) 24%); } .inner2 { background-image: linear-gradient(40deg, rgba(45, 71, 150, 1) 4%, rgba(95, 91, 165, 1) 23%, rgba(143, 106, 174, 1) 40%, rgba(185, 86, 230, 1) 52%, rgba(219, 111, 150, 1) 67%, rgba(245, 150, 59, 1) 77%, rgba(247, 165, 103, 1) 84%, rgba(216, 175, 104, 1) 94%); } .inner3 { background-image: repeating-linear-gradient(135deg, rgba(224, 110, 170, 1) 5% 10%, rgba(255, 255, 255, 1) 10% 15%, rgba(85, 85, 85, 1) 15% 20%, rgba(255, 255, 255, 1) 20% 25%); } </style>
Googleで「javascript マウスドラッグスクロール」で検索すると、サンプルが沢山ヒットします。とても良く出来ているのですが・・・どれもjQueryで書かれたものばかりです。でも、本当にとても考えられて良く出来ているので、これをバニラなJavaScriptで書き直します。
function mousedragscrollable(element){ let target; const elms = document.querySelectorAll(element); for(let i=0; i<elms.length; i++){ elms[i].addEventListener('mousedown', function(evt){ evt.preventDefault(); target = elms[i]; target.dataset.down = 'true'; target.dataset.move = 'false'; target.dataset.x = evt.clientX; target.dataset.y = evt.clientY; target.dataset.scrollleft = target.scrollLeft; target.dataset.scrolltop = target.scrollTop; evt.stopPropagation(); }); elms[i].addEventListener('click', function(evt){ if(elms[i].detaset != null && elms[i].detaset.move == 'true') evt.stopPropagation(); }); } document.addEventListener('mousemove', function(evt){ if(target != null && target.dataset.down == 'true'){ evt.preventDefault(); let move_x = parseInt(target.dataset.x) - evt.clientX; let move_y = parseInt(target.dataset.y) - evt.clientY; if (move_x !== 0 || move_y !== 0) { target.dataset.move = 'true'; } else { return; } target.scrollLeft = parseInt(target.dataset.scrollleft) + move_x; target.scrollTop = parseInt(target.dataset.scrolltop) + move_y; evt.stopPropagation(); } }); document.addEventListener('mouseup', function(evt){ if(target != null && target.dataset.down == 'true'){ target.dataset.down = 'false'; evt.stopPropagation(); } }); } window.addEventListener('DOMContentLoaded', function(){ mousedragscrollable('.wrap'); });
※PCで試してみてください。
全てのブラウザで試したわけでは無いのですが、マウスドラッグでスクロールできるようになったと思います。
最後に
2021年、ECサイトプラットホームであるShopifyは、Reactベースのフレームワーク「Hydrogen」を発表しました。
Hydrogenを使用するにはNode.jsが動作するWEBサーバーが必要になりますが、同じくReactベースのフレームワークであるNext.jsのSSRとCSRの弱点を改善した「ストリーミングSSR」等の機能があり、Shopifyをバックオフィス、つまりヘッドレスコマースとして使用しフロントエンドと切り離す様な使い方をすると、フロントエンドの表示高速化が期待できます。詳しくはShopify公式ブログ「Hydrogenを使用したストアフロントはなぜパフォーマンスが高いのか」を御覧ください。
私見ですが、jQueryに限らずJavaScriptは要素を手続き的に取得していかなければならない上にDOM操作後にどのようなHTML構造になるのかコードからは分かりにくいという欠点を持っており、規模が大きくなるほど複雑になっていきます。そのためWEBアプリ系の世界でのJavaScriptライブラリの主流はjQueryからReactに、あるいはフレームワークであるVue.jsやAngularとかに移行しつつある雰囲気で、私自身もWEBアプリ制作でのUI部分はすっかりReactやVue.js等に頼ってます。
しかしWEBページコンテンツ制作の方の世界では、HTMLとCSSでページを作ってそこにJavaScriptで動きをつけていく手順が主流であり、テンプレートをJSX内に記述する必要があるReactが向いているとは思えません。代わりに、小規模開発に向いていてHTMLをそのままテンプレート化できて更に双方向バインディングまでできるVue.jsをCDNで読み込んで使用するのがとても手軽で、そこで更にDOMをトラバースしたい時とかにjQuery等を併用するのが制作効率が高そうだと感じています。