Javascript を Windows8のタッチ操作に対応させるため「MSPointer」について調べてみた覚書です。
サンプルプログラムも作ってみました。
※プログラム初心者のため、このページのプログラムソースは正常に動作しない事がありますご注意下さい。
(あっちこっちのサイトの情報を寄せ集めてるので思わぬ不具合があるかも)
MSPointerについて
・タッチパネル・マウス・ペンなどの入力に対応している。
・従来のマウスイベントに準拠しており、プログラムを大きく改変せず導入可能。
(実際には色々変更する必要があるけど)
・MSのベンダープレフィックスからわかると思うがWindows8 + InternetExplorer10用
イベント
MSPointerDown
・タッチや右左クリックした時に発火
MSPointerOver
・マウスが領域に入った時に発火
MSPointerMove
・タッチして動かした時に発火
・マウスを動かした時に発火
MSPointerUp
・タッチやクリック終了時に発火
MSPointerOut
・タッチした状態でエリア外に出た時に発火
MSPointerCance
・同時タッチポイント数以上にタッチした時に発火?(当方で確認できず不明)
注意が必要なのはMSPointerMoveの挙動で、タッチ時では「タッチした状態」での移動でのみ発生するが、マウス時は「クリックに関係無く」上で移動するだけで発生するため、マウス時はただの移動かクリック(ドラッグ)しての移動か判断する必要がある。と言ってもmousemoveイベントと同じ
使い方(概要)
ブラウザのパンとズームを止めるため、イベント処理を行う要素(DIV等)のスタイルシートに下記を設定をする。これをしないとマルチタッチは使えない。
-ms-touch-action: none;
対応端末か判定
対応していない端末でMSPointerDownなどイベントを登録するとエラーが出るため必須。
実際の運用では、elseの以降部分に以前のマウスイベントなどを書き込む。
if (window.navigator.msPointerEnabled) {
//対応してます、ここにMSpainterイベントを登録する
}else{
//対応してない
}
イベントを登録
.addEventListener('MSPointerDown' ,function(e){ });
.addEventListener('MSPointerOver' ,function(e){ });
.addEventListener('MSPointerMove' ,function(e){ });
.addEventListener('MSPointerUp' ,function(e){ });
.addEventListener('MSPointerOut' ,function(e){ });
.addEventListener('MSPointerCancel,function(e){ });
取得できる値
基本的にはマウスイベントの値がそのまま使える。
(例えば座標のoffsetX/Y ・pageX/Y・screenX/Yなど)
増えているのは、
var num = navigator.msMaxTouchPoints;
端末のマルチタッチできる最大数
5タッチ対応なら=5
マウスのみなら=0
var num = event.pointerId;
タッチした順番に割り当てられる固有の番号
指が離れない限り番号を保持する。
マウスだと常に1
タッチだと押す度に番号がどんどん増えていく。
(番号の上限は不明で0に戻るのかも不明)
var bool = event.isPrimary;
最初のタッチにtrue、2本目以降はfalse
注意が必要なのは
2本でタッチしている時、先にtrueの1本目を離すとtrueが1本も無くなる。
その状態でさらにタッチしてもfalseしか出ず、全部の指を離さないとtrueが取得できない。
デモプログラム
タッチすると取得できた情報を表示するだけのプログラムです。
>http://www.achiachi.net/objectvr/javascript_test/mspointer.html
スマホのタッチイベントと大きく異なる点
・イベントの発火条件の違い
タッチイベントは2本の指が同時にうごいてもtouchmoveイベントが1つしか発生せず、1イベントで複数の指のタッチ状態(touches[]など)を取得できます。
msPointerは1タッチ=1イベントで、2本の指が動くと2つのMSPointerMoveが発生し、自分で配列などを作ってタッチ状態を管理しない限り、イベントの発生している指以外のタッチ状態を把握する事はできません。
・タッチ情報の管理の違い
タッチイベントの場合はtouches[]などの配列にタッチした順番に情報が保持され、先にタッチした指が離れた場合は自動的に配列を並べ替えてくれます。
msPointerはイベント発生時にタッチ状態が渡されますが、配列に保持される事は無いので別の指がタッチした時に利用できません。また指のタッチの順番は
event.isPrimaryが順番なのでなんとなく推測できますが、上に書いたように番号の上限がわからないし0に戻るのかも不明なのでそのまま使えません。
タッチ順番を保持する方法
とりあえず考えのみ忘れないよう書いておく
1.必要な配列の数を navigator.msMaxTouchPoints から取得
2.MSPointerDown発生時
event.pointerIdをキーとし「順番」に配列に格納
3.MSPointerMove発生時
配列からevent.pointerIdが一致する物を探し情報をアップデート
4.MSPointerUp/Out/Cancel発生時
配列からevent.pointerIdが一致する物を探し情報を削除し「配列を詰める」
※上記では領域外にOutしてまたOverしたものは無視する仕様
再Over時にキー配列の最後に加えても良いが、マウスの場合はOver時にクリックしてるか判断が必要になる。またタッチ入力ならpointerIdがOut時と変わってなければちょっと領域外に出ただけと判断できるが、マウスの場合はpointerIdが常に変わらないのため領域外でクリックを外して再クリックしても判断できないため。