🐭

jQuery:フリック操作ができる画像スクロールの実装について

2023/08/29に公開

メモから書き出しなので、もしかしたら別のサイトで紹介されてるかも…

概要

クライアントからの依頼でよく横長の画像をスクロールさせたい、というのがよくあります。何も考えなければoverflow:scrollだけで実装完了!なのですが、スマホ社会においてフリックで操作できることはもはや必須でしょう。でも、現状スクロールバーを使わなければスクロールってできないんですよね。(iPhone12,safari16.1)
なのでjQueryで実装します。

コード

まずはコード

<figure class="wrap"> <img src="images/hogehoge.png" alt="hogehoge"> </figure>
.wrap{
  width:100%;
  overflow-x: scroll;
  //ここから下はスクロールバー削除のため
  -ms-overflow-style: none;
  scrollbar-width: none;
  &::-webkit-scrollbar{
    display: none;
  }
  img{
    display: block;
    max-width: none;
    width:1920px;//ここはお好みで
    height:1920px;//ここはお好みで
  }
}
jQuery.prototype.mousedragscrollable = function () {
  let target;
  $(this).each(function (i, e) {
    $(e).mousedown(function (event) {
      event.preventDefault();
      target = $(e);
      $(e).data({
        down: true,//要素がクリックされているフラグ
        move: false,//要素がスクロールしているフラグ
        x: event.clientX,//マウスの水平位置
        y: event.clientY,//マウスの垂直位置
        scrollleft: $(e).scrollLeft(),//左からのスクロール位置
        scrolltop: $(e).scrollTop(),//上からのスクロール位置
      });
      return false;
      //各所でfalseが設定されているのは、ブラウザのデフォルト動作を消すため
    });
    $(e).click(function (event) {
      if ($(e).data("move")) {//data属性で要素がドラッグされているフラグを取得
        return false;
      }
    });
  });
  $(document)
    .mousemove(function (event) {
      if ($(target).data("down")) {//data属性で要素がマウスダウンされているフラグを取得
        event.preventDefault();
        let move_x = $(target).data("x") - event.clientX;
        let move_y = $(target).data("y") - event.clientY;
        if (move_x !== 0 || move_y !== 0) {
          $(target).data("move", true);
        } else {
          return;
        }
        $(target).scrollLeft($(target).data("scrollleft") + move_x);
        $(target).scrollTop($(target).data("scrolltop") + move_y);
        return false;
      }
    })
    .mouseup(function (event) {
      $(target).data("down", false);//上のマウスダウンされているフラグをマウスアップされた段階でオフにする
      return false;
    });
};
$(".wrap").mousedragscrollable();

解説

かなり単純なものなのでコメントアウトされている部分でおおむね開設できていると思いますが、一応自分がわからなかったところピックアップ。

-ms-overflow-style: none;
  scrollbar-width: none;
  &::-webkit-scrollbar{
    display: none;
  }

safariやchrome、FireFoxでスクロールバーを削除するためのスタイル指定。一括では指定できないのでSCSSの変数として登録してもいいかも。

jQuery.prototype.mousedragscrollable = function () {...}

あまり見たことなかったが、jQuery.prototypeを宣言しmousedragscrollableという関数をコールバックとして登録している。コールバックを使用しなくても上記は実装できそうだが、その場合もっとコードが長くなるのでこれが適切?

補足

もし画像部分にキャプションをつけたいなら、figcaptionではなく外側にキャプション要素をつけるほうがいい。

<div class="overwrap">
  <figure class="wrap"> <img src="images/hogehoge.png" alt="hogehoge"> </figure>
  <p class="caption>hogehoge</p>
</div>

理由としては、.wrap内にcaptionを置いてしまうと画像と同時にスクロールしてしまうので、挙動としてバグのように見えてしまう。
上記のdom構成にして、.overwrapにposition:relative、.captionにposition:absoluteでも設定して画像の上に乗せるとキャプションっぽく見えます。

以上です。ご覧いただきありがとうございました。

Discussion