以前「【祝】Chromebook Spin 11 での筆圧検知のやり方がわかったぞ!!」という記事で、JavaScript で筆圧検知を行う方法をご紹介しました。この筆圧検知のコードなんですが、iPad の Apple Pencil と同じコードで実装できるため非常に便利なんですが、一点問題がありました。
それは、iPad + Apple Pencil では指で触ったときに筆圧が
でも Chrome アプリ版の Google Keep や Android アプリの Adobe Draw なんかは何故か Chromebook Spin 11 でも指とペンを判別していたんです。どこを見れば判別できるんだろう...と悩み続けて 7 ヶ月 (放置してただけですが)、ついに判別方法を見つけました!!
ということで早速ご紹介しましょう!
タッチの開始・移動時に発火されるイベント
さてこの
さてここで、冒頭にも書いたように、Chromebook Spin 11 含む EMR ペン端末や Android では、指で触っていてもこの
プロパティ名からも予想できるように、
つまり、この
完璧ですね!(知らんけど)
ただ、Chromebook Spin 11 でしか検証できていないので こちらの検証ツール で他の端末でもお試しいただけないでしょうか...?よろしくお願いします...!
それは、iPad + Apple Pencil では指で触ったときに筆圧が
null
になるのに対し、Chromebook Spin 11 (に限らずたぶん EMR ペン端末は) 指で触ったときにも筆圧を検知してしまうんです (Android に関してはおそらく触れている面積から擬似的に筆圧を定義している)。これの何が困るかというと、指の場合も EMR ペンの場合も筆圧を検知しているので、指で触っているのかペンで描いているのかが判別できないということで、お絵かきアプリを自作しても指で描いた線にも太さの強弱が反映されてしまうんです。でも Chrome アプリ版の Google Keep や Android アプリの Adobe Draw なんかは何故か Chromebook Spin 11 でも指とペンを判別していたんです。どこを見れば判別できるんだろう...と悩み続けて 7 ヶ月 (放置してただけですが)、ついに判別方法を見つけました!!
ということで早速ご紹介しましょう!
答えは Touch オブジェクトにあった
タッチの開始・移動時に発火されるイベント
touchstart
touchmove
において与えられる TouchEvent
オブジェクトには、そのタイミングで触られた画面上の点に関する情報を含む Touch
オブジェクトを格納した TouchList
オブジェクトが touches
プロパティに格納されています。
document.body.addEventListener("touchstart",e=>{
// e ... TouchEvent オブジェクト
let touches = e.touches // touches ... TouchList オブジェクト
}
さてこの
TouchList
オブジェクトから for
なりなんなりでそれぞれの Touch
オブジェクトを取り出しましょう。Touch
オブジェクトはそのタイミングで触れていた指またはペンの個数分存在します。
document.body.addEventListener("touchstart",e=>{
// e ... TouchEvent オブジェクト
let touches = e.touches // touches ... TouchList オブジェクト
for(let touch of touches) { // touch ... Touch オブジェクト
}
}
Touch
オブジェクトには、個々の触れた点に関する情報が格納されていますが、基本的に使用されるのはウィンドウ上での座標です。これらはそれぞれ clientX
, clientY
プロパティに格納されています。筆圧は force
プロパティに格納されています。
document.body.addEventListener("touchstart",e=>{
// e ... TouchEvent オブジェクト
let touches = e.touches // touches ... TouchList オブジェクト
for(let touch of touches) { // touch ... Touch オブジェクト
console.log(`X: ${touch.clientX}\nY: ${touch.clientY}\nF: ${touch.force}`);
}
}
さてここで、冒頭にも書いたように、Chromebook Spin 11 含む EMR ペン端末や Android では、指で触っていてもこの
force
に数値が格納されています。このため、iPad + Apple Pencil のように if(!touch.force)
のようにして指とペンを見分けることはできません。
ここで一度、Touch
オブジェクトの中身を見てみましょう。
▲ 指でタッチしたとき
▲ Chromebook Spin 11 純正 EMR ペンでタッチしたとき
clientX
, clientY
や screenX
, screenY
そして force
が異なるのは当然として、1 つだけアヤシイ数値がペンの方にあります。radiusX
, radiusY
プロパティです。なんだこのキレイな数値は。プロパティ名からも予想できるように、
radiusX
, radiusY
プロパティは接触領域を楕円に近似した場合の X 軸方向と Y 軸方向の半径を表すようです。指でタッチした場合は押し付け方によってこの値はバラバラでした。しかしペンでタッチした場合はどのようにタッチしても 0.5
となりました。つまり、この
radiusX
と radiusY
の値が共に 0.5
のときは (たぶん) ペンによる接触だと判断できるわけです!!ということでコードはこんな感じです。
document.body.addEventListener("touchstart",e=>{
// e ... TouchEvent オブジェクト
let touches = e.touches // touches ... TouchList オブジェクト
for(let touch of touches) { // touch ... Touch オブジェクト
if(touch.radiusX === 0.5 && touch.radiusY === 0.5) console.log(`F: ${touch.force}`); // ペンによるタッチ
else console.log("F: null"); // 指によるタッチ
}
}
完璧ですね!(知らんけど)
ただ、Chromebook Spin 11 でしか検証できていないので こちらの検証ツール で他の端末でもお試しいただけないでしょうか...?よろしくお願いします...!
コメント
コメントを投稿