logo

canvas上でピンチイン/ピンチアウトを可能にする

Canvas上に線を引くイベントをtouchmoveにつけると、スマートフォンでピンチイン・ピンチアウトなどをしようとした時に、線が引かれるようになってしまう。
ウェブ開発をしたことある人なら、Canvas外で操作すれば、問題ないことを知っているだろうけど、普通はそういうことには気がつかないことが大半だろうと思われる。
利用者にとってCanvasを使いやすくするためには、その点も配慮したほうが使いやすくなるはずである。

実装例

<div id="wrap"> <canvas id="canvas" /> </div> <style> #wrap { width: 100vw; height: 100vh; position: relative; } #canvas { position: absolute; width: 500px; height: 200px; top: 0; bottom: 0; right: 0; left: 0; margin: auto; } </style>
const canvas = document.getElementById('canvas'); const canvasWrapper = document.getElementById('wrap'); // @var {Bool} isDrawing 描画可能か let isDrawing = false; canvasWrapper.addEventListener('touchstart', (event) => { if ( event.touches.length === 1 && document.elementFromPoint(event.touches[0].clientX, event.touches[0].clientY) === canvas ) { isDrawing = true; } else { // canvasWrapperとcanvasの境目辺りをタッチした場合、稀にスクロールイベントが先に発火してしまうことがある。 // それを抑制するために、イベントの伝播を止める event.stopPropagation(); isDrawing = false; } }); canvas.addEventListener('touchmove', (event) => { if (!isDrawing) { return; } event.preventDefault(); // ここに描画処理 });

touchstart イベントは、canvasではなく親要素に付けているところがポイント。