スマートフォンなどで,連続スワイプのハンドリング方法をまとめておきます.
指が触れ始めたときのDOMや,離れた瞬間のDOMは簡単に取得できましたが,「今」指が触れているDOMを取得するのに苦戦しました.
先日行ったデザインリニューアル(YutaroTanaka.com)でも,この方法を使ってスマホのスワイプ対応をしています.
やりたいこと
「このような要素をタッチしたときに,触れたところの色を変えたい」 「ひとつひとつタップするのではなく,指でなぞった部分の色を変えたい」タッチ対象は,下記のような spanタグを用意して,CSSで成形します.
[code language=“html” title=“HTML”] <span class="panel">1</span> <span class="panel">2</span> ・・・ <span class="panel">20</span> [/code]
【PC】mouseenter イベントをハンドリングする
$('.panel') でタッチ対象の要素を取得し,.on() で mouseenter イベントにイベントハンドラをセットします.ハンドラ内では,タッチ対象が class = “panel” を持っているとき,背景色を変えます.
(今回は class = “green” に対して CSS で背景色をつけています)
[code language=“javascript” title=“JavaScript”] $().ready(function () { $('.panel').on({ ‘mouseenter’: function () { var target = $(this); if (target.hasClass(‘panel’)) { target.addClass(‘green’); } } }); }); [/code]
マウスが触れた瞬間に,その要素の色が変化します.
【スマホ①】touchstart, touchend, touchmove を試すも...
touchstart, touchend, touchmove などのイベントが発生した時の要素の要素取得を試みました.ハンドラ内の記述「var target = $(this); 」で取得できるのは,タッチした瞬間の要素です.
そのため,スマホに指をつけたときの要素は色が変るけど,指を放さずに画面上を動かしても,target は変化しません.
[code language=“javascript” title=“JavaScript”] $().ready(function () { $('.panel').on({ ‘touchmove’: function (event) { var target = $(this); if (target.hasClass(‘panel’)) { target.addClass(‘green’); } } }); }); [/code]
また,event オブジェクトの持つ event.originalEvent の,changedTouches, currentTarget, target, targetTouches, touches, … などでは,指が触れているDOMは取得できず,結果は同じでした.
[code language=“javascript” title=“JavaScript”] $().ready(function () { $('.panel').on({ ‘touchmove’: function (event) { var target = event.XXXXXXX; if (target.hasClass(‘panel’)) { target.addClass(‘green’); } } }); }); [/code]
【スマホ②】touchmove + position + elementFromPoint
試行錯誤した結果,「touchmove イベント時のハンドラ内で,event が起こったポジションを取得し,そのポジションにある要素を取得する.」
これで解決しました.
touchmove イベントは,タッチデバイスの画面を指でなぞっている間連続して発生します.
その際に,event オブジェクトで取得できる指の座標を,指定された座標上にある要素を取得できるdocument.elementFromPoint(X, Y) に渡します.
[code language=“javascript” title=“JavaScript”] $().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');
}
}
}); [/code]
まとめ
最終的には下記の通り,mouseenter, touchmove イベントにそれぞれハンドラをセットすることで,PCでもスマートフォンでも連続タッチイベントが取得できました.[code language=“javascript” title=“JavaScript”] $('.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');
}
}
});
[/code]
イベントをハンドルするときに,座標からアプローチするという発想がなかなか出てこなかったので,メモです.
-
- 上記を利用してリニューアルしたページ
YutaroTanaka.COm
-
- デモ
DEMO(JSFIDDLE)