やりたいこと
マウスで動作するJavaScriptのコードがペンタブレットで動作しませんでした。
この記事では著者の修正した箇所をまとめておきます。
修正したアプリはCanvasに絵を描くアプリです。アプリをペンタブレットに対応するにあたって修正した箇所のみの紹介です。(ペンタブレット/マウス両方で動作するように修正します。)
スマホ/タブレット対応に関して
スマホ/タブレット対応は基本的にペンタブレットの対応と同様のはずですが、動作確認を行っていません。
問題点と修正
マウス関係のイベントが来ない
ペンタブレットで操作した場合にmousedown、mousemove、mouseupのイベントが来ませんでした。
ペンタブレットではmouseのイベントではなくtouchのイベントが来ます。
各イベントは以下のように置き換える必要があります。
置き換え前(mouse) | 置き換え後(touch) |
mousedown | touchstart |
mousemove | touchmove |
mouseup | touchend |
ここではマウスとペンタブレットを同様に動作させるために実際には以下のように修正しました。(マウス操作時/ペンタブレット操作時に同じ関数を呼ぶようにしました。)
修正前:
canvas.addEventListener('mousedown', startDrag, false);
canvas.addEventListener('mousemove', whileDrag, false);
canvas.addEventListener('mouseup', endDrag, false);
修正後:
canvas.addEventListener('mousedown', startDrag, false);
canvas.addEventListener('touchstart', startDrag, false);
canvas.addEventListener('mousemove', whileDrag, false);
canvas.addEventListener('touchmove', whileDrag, false);
canvas.addEventListener('mouseup', endDrag, false);
canvas.addEventListener('touchend', endDrag, false);
clickイベントはペンタブレットでも来ます。修正不要です。
EventからoffsetX/offsetYが取得できない
上記の修正でeventは来るようになりますが、コールバックの引数であるeventからevent.offsetX/offsetYが取得できません。
touchのイベントとmouseのイベントが異なるためです。またtouchのイベントにはoffsetX/offsetYがありません。そのため以下のように計算する必要があります。
elementは基準とするelementです。document.getElementByIdなどで取得してください。
const offsetX = event.touches[0].clientX - element.getBoundingClientRect().left
const offsetY = event.touches[0].clientY - element.getBoundingClientRect().top
マウスとペンタブレットでどちらでも動作するように以下のような関数を作りました。
event.offsetX/Yがあればそのまま返し、なければ計算して返します。
function getOffesetX(event,id) {
if (event.offsetX != undefined) return event.offsetX;
return event.touches[0].clientX - document.getElementById(id).getBoundingClientRect().left
}
function getOffesetY(event,id) {
if (event.offsetY != undefined) return event.offsetY;
return event.touches[0].clientY - document.getElementById(id).getBoundingClientRect().top
}
ここではoffsetX/Yに触れていますが、clientX /Yなどの座標情報も event.clientXも存在しません。event.touches[0]下に保存されています。(touchesが配列なのはスマホなどで同時に複数タッチされる可能性があるため)詳細は以下のページをご参照ください。

ペン移動(ドラッグ)中にスクロールする
ペンを上下させたときにアプリが想定通りに動くと同時にブラウザがスクロールするようになってしまいました。
以下の方法でドラッグ中にブラウザの初期動作を止めることでスクロールしないようにすることが可能です。
preventDefaultの使用
以下のようにtouchmoveイベントで呼ばれる関数の中でevent.preventDefault()を呼ぶことで初期動作を止めることができます。
注意
以下のページに気になることが書いてありました。ブラウザによりpreventDefaultが効かない可能性があります。
想定通りに動作しない場合は以下の修正で治るかもしれません。
修正前:
canvas.addEventListener('mousemove', whileDrag, false);
修正後:
canvas.addEventListener('mousemove', whileDrag, {passive:false});

canvas.addEventListener('touchmove', whileDrag, false);
function whileDrag(event) {
event.preventDefault()
結果
対象としたアプリは上記の点を修正することでペンタブレットでも動作するようになりました。
コメント