イナヅマTVログ

【Canvas練習ノート】マウス(タッチ)操作 – ドラッグとか

| 2件のコメント

Canvasに描いた形状に対するマウス(MouseEvent, TouchEvent)操作。
DOM elementやFlash MovieClipなら当たり前にできることをCanvasに実装するのはなかなかの面倒くささです。

Canvas上のオブジェクトにマウス(タッチ)操作を実現する方法は2通りありそうです。
1. DOM element, MovieClipのようにオブジェクトそのものにaddEventListenerできるようにする。
2. ある点(Position)にヒットするオブジェクトを描画が最後のものから配列で返す機能を提供する。
*他にもあるでしょうか?ご存知の方はお教え下さい。

1の方が扱いやすいですがプログラムが複雑になりそうだったので2の方法で実装を試みました。
three.jsが同様の方法をとっていたというのもあります。

どちらの方法をとるにせよ描画オブジェクトを一括管理する必要があります。

ドラッグ demo
drag

Mouse(Touch) 座標

まずCanvas上のマウス座標(Point)を取得します。

<canvas id="canvas" width="640" height="480"></canvas>

Canvas elementを取得しEventを監視します。
PCではMouse Eventを使用します。

var canvas = document.getElementById( "canvas");
 
function onDown ( e ) {
    var x = e.pageX,
        y = e.pageY;
 
    x -= canvas.offsetLeft;
    y -= canvas.offsetTop;
}
 
function onUp () {
 
}
 
canvas.addEventListener( "mousedown", onDown, false );
canvas.addEventListener( "mouseup", onUp, false );

スマホではTouch Eventです。

// 省略
 
canvas.addEventListener( "touchstart", onDown, false );
canvas.addEventListener( "touchend", onUp, false );

マウス(タッチ)座標からcanvasのオフセットを減算します。
pageX, pageYが取得できない場合はこちらを参考にするとよいかもです。
stackoverflow: How do I get the coordinates of a mouse click on a canvas element?

x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; 
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;

あたり判定

座標がオブジェクト内かどうかのあたり判定が必要です。

四角

形状が四角の場合。
Algorithm to determine if a point is inside a square with mathematics (no hit test involved)
ActionScript の解説ですけど分かりやすく参考になりました。

他にも有益な情報がネット上にたくさんありました。
How to check if a point is inside a rectangle
stackoverflow: Finding whether a point lies inside a rectangle or not
MATHEMATICS: How to check if a point is inside a rectangle?

三角

形状が三角の場合は四角から1点少なくなるのでチェックが楽になります。

stackoverflow: How to determine a point in a triangle?
Point in triangle test

円はもっと楽そうです。

stackoverfow: Equation for testing if a point is inside a circle
MATHEMATICS: Equation of a circle with radius and contains 2 points

ドラッグ

mousedown(touchstart)後mousemove(touchmove)を監視しmouseup(touchend)で監視を止めます。

ドラッグ開始時に描画を一番上にしたい時は描画順の変更機能も必要になります。

スマホではドラッグ開始時にブラウザスクロールを止めた方がなめらかにドラッグ可能です。

function onDown ( e ) {
    var x = e.pageX,
        y = e.pageY;
 
    x -= canvas.offsetLeft;
    y -= canvas.offsetTop;
 
    // ブラウザスクロールを止める
    e.preventDefault();
}
 
canvas.addEventListener( "touchstart", onDown, false );

*ブラウザがスクロールできないと、とてもとても使いにくくなるので「ドラッグ可能なら」など限定的に使用すると良いかと思います。

demo
drag

*上部リンクと同じものです。

2件のコメント

  1. ピンバック: Canvas始めました – マウスアクション(click)を使う最初の一歩 « イナヅマTVログ

  2. ピンバック: Canvas 2Dライブラリを作ろうとして感じたこととDisplayObject « イナヅマTVログ

コメントを残す