64
61

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【スマホ対応】jQuery 連続スワイプイベントをハンドリングする方法

Last updated at Posted at 2014-08-10

スマートフォンなどで、連続スワイプのハンドリング方法をまとめる。

指が触れ始めたときのDOMや、離れた瞬間のDOMは簡単に取得できるが
「今」指が触れているDOMを取得するのに苦戦した。

先日行ったホームページのデザインリニューアルでも
この方法を使ってスマホのスワイプ対応をした。

やりたいこと

「このような要素をタッチしたときに、触れたところの色を変えたい」
「ひとつひとつタップするのではなく、指でなぞった部分の色を変えたい」

TouchSequence.png

タッチ対象は、下記のような spanタグを用意して、CSSで成形する。

html
<span class="panel">1</span>
<span class="panel">2</span>
 ・・・
<span class="panel">20</span>

(PC)mouseenter イベントをハンドリングする

$(‘.panel’) でタッチ対象の要素を取得し、.on() で mouseenter イベントにイベントハンドラをセットする。

ハンドラ内では、タッチ対象が class = “panel” を持っているとき、背景色を変える。
(今回は class = “green” に対して CSS で背景色をつけている)

js
$().ready(function () {
    $('.panel').on({
        'mouseenter': function () {
            var target = $(this);
            if (target.hasClass('panel')) {
                target.addClass('green');
            }
        }
    });
});

マウスが触れた瞬間に、その要素の色が変化する。

TouchSequence-2.png

PCは余裕

(スマホ)touchstart, touchend, touchmove など → ×

touchstart, touchend, touchmove などのイベントが発生した時の要素の要素取得を試みた。

ハンドラ内の記述「var target = $(this); 」で取得できるのは、タッチした瞬間の要素。
そのため、スマホに指をつけたときの要素は色が変るけど、指を放さずに画面上を動かしても、target は変化しない。

js
$().ready(function () {
 $('.panel').on({
        'touchmove': function (event) {
            var target = $(this);
            if (target.hasClass('panel')) {
                target.addClass('green');
            }
        }
    });
});

また、event オブジェクトの持つ event.originalEvent の、changedTouches, currentTarget, target, targetTouches, touches, … などでは、指が触れているDOMは取得できず、結果は同じ。

js
$().ready(function () {
 $('.panel').on({
        'touchmove': function (event) {
            var target = event.XXXXXXX;
            if (target.hasClass('panel')) {
                target.addClass('green');
            }
        }
    });
});

(スマホ)touchmove + position + elementFromPoint → ○

試行錯誤した結果、
「touchmove イベント時のハンドラ内で、event が起こったポジションを取得し、そのポジションにある要素を取得する。」
これで解決した。

touchmove イベントは、タッチデバイスの画面を指でなぞっている間連続して発生する。
その際に、event オブジェクトで取得できる指の座標をdocument.elementFromPoint(X, Y) に渡す。
これによって、指定された座標上にある要素を取得できる

js
$().ready(function () {
    $('.panel').on({
        'touchmove': function (event) {
            var touch = event.originalEvent.touches[0];
            var target = $(document.elementFromPoint(touch.clientX, touch.clientY));
 
            if (target.hasClass('panel')) {
                target.addClass('green');
            }
        }
  });

まとめ

最終的には下記の通り、mouseenter, touchmove イベントにそれぞれハンドラをセットすることで、PCでもスマートフォンでも連続タッチイベントが取得できた。

js
$('.panel').on({
    'mouseenter': function () {
        var target = $(this);
        if (target.hasClass('panel')) {
            target.addClass('green');
        }
    },
    'touchmove': function (event) {
        var touch = event.originalEvent.touches[0];
        var target = $(document.elementFromPoint(touch.clientX, touch.clientY));
 
        if (target.hasClass('panel')) {
            target.addClass('green');
        }
    }
});

イベントをハンドルするときに、座標からアプローチするという発想がなかなか出てこなかったので、メモ。

64
61
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
64
61

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?