Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

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

指が触れ始めたときの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');
        }
    }
});

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

tanakaworld
A Software Engineer. Creator of proff.io
https://tanaka.world
mercari
フリマアプリ「メルカリ」を、グローバルで開発しています。
https://tech.mercari.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした