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等を併用するのが制作効率が高そうだと感じています。