この記事では、スマートフォンやタブレット等によるタッチ操作をJavaScriptで取り扱うことができるtouchイベントについて、できるだけ簡単に解説します。
Web上に丁寧な記事はいくつもあったんだけど、正直、初心者プログラマーの僕には難しかった・・・。
執筆者も初心者で最近悩んだばかりだから、初心者の気持ちになった記事にできているかも・・・??
(簡単にするために、ちょっと大雑把な説明になります)
タッチイベントの種類
ユーザーが、画面をタッチで操作すると、操作の内容によって、以下のようなイベントが発生します。
イベント | 発生するタイミング |
---|---|
touchstart | タッチ面に指が触れた時 |
touchend | タッチしていた指を離した時 |
touchmove | タッチしながら指を移動させた時 |
touchcancel | 何らかの理由でタッチが取り消された時 |
まずは、下記のサンプルで、タッチイベント発生のイメージをつかんでください。
*touch areaに指を触れたり、離したり、動かしたりすると、発生したイベントと時刻がdisplay areaに表示されます。
touch area
display area
このデモのソースコードは下記のとおりです。
<div id="container1"> <p>touch area</p> <div id="touch-area1"></div> <p>display area</p> <div id="display-area1"></div> </div> <script> const displayArea1 = document.getElementById("display-area1") const touchArea1 = document.getElementById("touch-area1") // touchstartイベント touchArea1.addEventListener("touchstart", () => { displayArea1.innerHTML = getTimeStamp() + " touchstart" }) // touchendイベント touchArea1.addEventListener("touchend", () => { displayArea1.innerHTML = getTimeStamp() + " touchend" }) // touchmoveイベント touchArea1.addEventListener("touchmove", () => { event.preventDefault(); // 画面スクロールを防止 displayArea1.innerHTML = getTimeStamp() + " touchmove" }) // touchcancelイベント touchArea1.addEventListener("touchcancel", () => { displayArea1.innerHTML = getTimeStamp() + " touchcacel" }) // タイムスタンプ取得 function getTimeStamp(){ const date = new Date() return ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2) + ':' + ('0' + date.getSeconds()).slice(-2) + ':' + ('0' + date.getMilliseconds()).slice(-3) } </script>
あれ? touch area の外に指を移動させたり、touch areaの外で指を離したりしてもイベントが発生するみたいだけど・・・?
それは私もハマったポイントよ。
例えば、touch areaに対して“touchend”のイベントリスナーを追加した場合、「touch area上でタッチを開始した指をスクリーンから離した時」にイベントが発火するわ。
「touch areaから指が離れた時」という条件ではない事に注意してね!“touchmove”も同じ考え方よ。
タッチの情報を取得する
先に説明したとおり、タッチを開始したり、指を動かしたり離したりすると、TouchEventが発生します。
TouchListとTouchオブジェクト
TouchEventオブジェクトは、3種のTouchListをもっており、その中に、タッチの情報(タッチした座標など)をもつTouchオブジェクトがあります。
下図は、この説明を図示したものです。
*指3本でタッチした後、さらにもう一本の指でタッチした時のイメージ
タッチしてる指の情報が3種類のタッチリストで確認できるんだね~
3種のTouchList
TouchEventは、下記3種のTouchListをもっています。
リストごとに、含まれるTouchオブジェクト(≒指の情報)が異なりますので、用途によって使い分けが必要です。
touches | すべてのTouchオブジェクトを格納 *さっきの例では、合計4本の指でタッチしているので4つ |
changedTouches | 変更されたTouchオブジェクトを格納 *さっきの例では、追加で③のタッチを行ったので、③の情報 |
targetTouches | イベントのターゲットと同じ要素でタッチを始めた Touchオブジェクトを格納 *さっきの例では、③のターゲットである#blue-area要素でタッチが始まった3つ(⓪,①,③) |
・・・で、どのリストを使えばいいの・・・?
う~ん、大体の場合はchangedTouchesを使えばいいんじゃないかな。
特に、指を離した時に、離した指の情報を取得できるのはchangedTouchesだけよ。
Touchオブジェクト
各タッチの情報は、Touchオブジェクトから取得することができます。
Touchオブジェクトは、触った指ごとに発生しますので、もし4本の指でタッチしたら4つのTouchオブジェクトが発生します。
Touchオブジェクトから取得できる主な情報は下表のとおりです。
identifier | 各タッチに付与される番号。 指のIDのようなもので、指を離すまではidentifierは変わりません |
screenX | 端末のスクリーンの左端からの距離(px) |
screenY | 端末のスクリーンの上端からの距離(px) |
clientX | ブラウザのビューポートの左端からの距離(px) |
clientY | ブラウザのビューポートの上端からの距離(px) |
pageX | ドキュメントの上端からの距離(px) |
pageY | ドキュメントの上端からの距離(px) |
target | その指をタッチ開始した位置にあるElement *指を移動しても、targetはタッチ開始時の位置のElementのまま |
いっぱいあるけど、つまりは、指のID と 座標の情報 って感じだね
page、screen、clientの値の違いは、下の図を見ればわかるわよ~
(参考として、HTML要素の座標についても右側に書いてみました。タッチした座標とHTML要素の座標を比較することが、よくあると思うので・・・)
TouchList・Touchオブジェクトを理解するためのサンプル
こちらもお試し用のサンプルを作ってみました。
3つのTouchListの違いや、Touchオブジェクトの中身が理解できると思います。
【JavaScript】初心者でもわかるタッチイベント(touch event)
この記事では、スマートフォンやタブレット等によるタッチ操作をJavaScriptで取り扱うことができるtouchイベントについて、できるだけ簡単に解説します。
Web上に丁寧な記事はいくつもあったんだけど、正直、初心者プログラマーの僕には難しかった・・・。
執筆者も初心者で最近悩んだばかりだから、初心者の気持ちになった記事にできているかも・・・??
(簡単にするために、ちょっと大雑把な説明になります)
タッチイベントの種類
ユーザーが、画面をタッチで操作すると、操作の内容によって、以下のようなイベントが発生します。
イベント | 発生するタイミング |
---|---|
touchstart | タッチ面に指が触れた時 |
touchend | タッチしていた指を離した時 |
touchmove | タッチしながら指を移動させた時 |
touchcancel | 何らかの理由でタッチが取り消された時 |
まずは、下記のサンプルで、タッチイベント発生のイメージをつかんでください。
*touch areaに指を触れたり、離したり、動かしたりすると、発生したイベントと時刻がdisplay areaに表示されます。
touch area
display area
このデモのソースコードは下記のとおりです。
<div id="container1"> <p>touch area</p> <div id="touch-area1"></div> <p>display area</p> <div id="display-area1"></div> </div> <script> const displayArea1 = document.getElementById("display-area1") const touchArea1 = document.getElementById("touch-area1") // touchstartイベント touchArea1.addEventListener("touchstart", () => { displayArea1.innerHTML = getTimeStamp() + " touchstart" }) // touchendイベント touchArea1.addEventListener("touchend", () => { displayArea1.innerHTML = getTimeStamp() + " touchend" }) // touchmoveイベント touchArea1.addEventListener("touchmove", () => { event.preventDefault(); // 画面スクロールを防止 displayArea1.innerHTML = getTimeStamp() + " touchmove" }) // touchcancelイベント touchArea1.addEventListener("touchcancel", () => { displayArea1.innerHTML = getTimeStamp() + " touchcacel" }) // タイムスタンプ取得 function getTimeStamp(){ const date = new Date() return ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2) + ':' + ('0' + date.getSeconds()).slice(-2) + ':' + ('0' + date.getMilliseconds()).slice(-3) } </script>
あれ? touch area の外に指を移動させたり、touch areaの外で指を離したりしてもイベントが発生するみたいだけど・・・?
それは私もハマったポイントよ。
例えば、touch areaに対して“touchend”のイベントリスナーを追加した場合、「touch area上でタッチを開始した指をスクリーンから離した時」にイベントが発火するわ。
「touch areaから指が離れた時」という条件ではない事に注意してね!“touchmove”も同じ考え方よ。
タッチの情報を取得する
先に説明したとおり、タッチを開始したり、指を動かしたり離したりすると、TouchEventが発生します。
TouchListとTouchオブジェクト
TouchEventオブジェクトは、3種のTouchListをもっており、その中に、タッチの情報(タッチした座標など)をもつTouchオブジェクトがあります。
下図は、この説明を図示したものです。
*指3本でタッチした後、さらにもう一本の指でタッチした時のイメージ
タッチしてる指の情報が3種類のタッチリストで確認できるんだね~
3種のTouchList
TouchEventは、下記3種のTouchListをもっています。
リストごとに、含まれるTouchオブジェクト(≒指の情報)が異なりますので、用途によって使い分けが必要です。
touches | すべてのTouchオブジェクトを格納 *さっきの例では、合計4本の指でタッチしているので4つ |
changedTouches | 変更されたTouchオブジェクトを格納 *さっきの例では、追加で③のタッチを行ったので、③の情報 |
targetTouches | イベントのターゲットと同じ要素でタッチを始めた Touchオブジェクトを格納 *さっきの例では、③のターゲットである#blue-area要素でタッチが始まった3つ(⓪,①,③) |
・・・で、どのリストを使えばいいの・・・?
う~ん、大体の場合はchangedTouchesを使えばいいんじゃないかな。
特に、指を離した時に、離した指の情報を取得できるのはchangedTouchesだけよ。
Touchオブジェクト
各タッチの情報は、Touchオブジェクトから取得することができます。
Touchオブジェクトは、触った指ごとに発生しますので、もし4本の指でタッチしたら4つのTouchオブジェクトが発生します。
Touchオブジェクトから取得できる主な情報は下表のとおりです。
identifier | 各タッチに付与される番号。 指のIDのようなもので、指を離すまではidentifierは変わりません |
screenX | 端末のスクリーンの左端からの距離(px) |
screenY | 端末のスクリーンの上端からの距離(px) |
clientX | ブラウザのビューポートの左端からの距離(px) |
clientY | ブラウザのビューポートの上端からの距離(px) |
pageX | ドキュメントの上端からの距離(px) |
pageY | ドキュメントの上端からの距離(px) |
target | その指をタッチ開始した位置にあるElement *指を移動しても、targetはタッチ開始時の位置のElementのまま |
いっぱいあるけど、つまりは、指のID と 座標の情報 って感じだね
page、screen、clientの値の違いは、下の図を見ればわかるわよ~
(参考として、HTML要素の座標についても右側に書いてみました。タッチした座標とHTML要素の座標を比較することが、よくあると思うので・・・)
TouchList・Touchオブジェクトを理解するためのサンプル
こちらもお試し用のサンプルを作ってみました。
3つのTouchListの違いや、Touchオブジェクトの中身が理解できると思います。
touch area
このサンプルのソースコードは以下のとおりです。
<div id="container2"> <p>touch area</p> <div id="touch-area2"> <div id="blue-area">blue</div> <div id="red-area">red</div> </div> <div> <span>touches</span> <button onclick="pushBtn('display-touches')">表示・非表示 切替</button> <div id="display-touches"></div> </div> <div> <span>changedTouches</span> <button onclick="pushBtn('display-changed-touches')">表示・非表示 切替</button> <div id="display-changed-touches"></div> </div> <div> <span>targetTouches</span> <button onclick="pushBtn('display-target-touches')">表示・非表示 切替</button> <div id="display-target-touches"></div> </div> </div> <script> // 要素の取得 const touchArea2 = document.getElementById("touch-area2") const displayTouches = document.getElementById("display-touches") const displayChangedTouches = document.getElementById("display-changed-touches") const displayTargetTouches = document.getElementById("display-target-touches") // 各タッチイベントのイベントリスナー登録 touchArea2.addEventListener("touchstart", function(){ updateDisplay(event) } ) touchArea2.addEventListener("touchend", function(){ updateDisplay(event) } ) touchArea2.addEventListener("touchmove",function(){ event.preventDefault() // 画面スクロールを防止 updateDisplay(event) } ) touchArea2.addEventListener("touchcancel",function(){ updateDisplay(event) } ) // タッチの情報を画面に表示する function updateDisplay(event){ displayTouches.innerHTML = getTouchInfo(event.touches) displayChangedTouches.innerHTML = getTouchInfo(event.changedTouches) displayTargetTouches.innerHTML = getTouchInfo(event.targetTouches) } // 与えられたタッチリストからタッチ情報を取得 function getTouchInfo(touchList){ let displayStr = "" for ( const touch of touchList ){ displayStr += ` identifier: ${touch.identifier}<br> screenX: ${touch.screenX}<br> screenY: ${touch.screenY}<br> clientX: ${touch.clientX}<br> clientY: ${touch.clientY}<br> pageX: ${touch.pageX}<br> pageY: ${touch.pageY}<br> target: ${touch.target.id}<br> --------------------------------------<br>` } return displayStr } // 表示・非表示ボタン function pushBtn(targetId){ document.getElementById(targetId).classList.toggle('hide') } </script>
勘違いしやすい(?)ポイント
他の人はどうかわかりませんが、私が勘違いしたポイントをメモしておきます。
1.touchmoveとtouchendの発火
誤:イベントリスナーを追加した要素の上で指を動かす・指を離すと発火
正:イベントリスナーを追加した要素の上でタッチを開始した指を動かす・離すと発火
2.TouchListに入っているtouchオブジェクト
誤:イベントリスナーを追加した要素の上でタッチした指の情報
正:スクリーンにタッチした指の情報
先ほどのサンプルで、タッチエリア以外の部分をタッチしながら、他の指でタッチエリアを触ると、この意味がわかると思います。
3.Touchオブジェクトのtarget
誤:現在触れているHTML要素
正:そのタッチを開始した時に触れたHTML要素
参考
touchイベントを初めて学んで作った成果物です
MDNのTouchの解説ページ
コメント