2016-05-15 1 views
0

HTML 5キャンバスで簡単なマップを作成しようとしています。マウスをドラッグすると地図が移動し、クリックすると最も近いウェイポイントが選択されます。しかし、問題があります。私がマウスをドラッグすると、私はそれを解放するときにクリックイベントをクリックします。私はクリックしている間動きがなかった場合にのみそれを取得したいと思います。html 5キャンバスでのク​​リックとドラッグの検出

私はのMouseMoveイベントハンドラで動かないのイベントを確認しようとしたが、成功しません:

function onMove(e) { 
    if(e.movementX == 0 && e.movementY == 0) { 
     console.log("a"); //never happens... 
    } 
} 

私の質問は:それを行うための簡単な方法があり、または私がチェックする必要がありますプレスとリリースのイベントが同じ場所にある場合は?ここで

は私のコードです:ここでは

function onMove(e) { 
    console.log("moving"); 
} 

function onClick(e) { 
    console.log("clicked"); 
} 

function init() { 
    c = document.getElementById("MapCanvas"); 
    ctx = c.getContext("2d"); 
    c.addEventListener("click", onClick, true); 
    c.addEventListener("mousemove", onMove, true); 
} 
+0

イベント・ハンドラとサンプルを投稿html。 [mcve] – yezzz

+0

を読んでください。クリックするのではなく、mousedownイベントを選択してみてください。 – ShuberFu

答えて

2

は、この問題を解決する一つの方法です:

我々は二つのフラグを必要とする二つの状態(いくつかのオブジェクトを好むを知っておく必要がありますとして - それはあなた次第です):

var isDown = false; // mouse button is held down 
var isMoving = false; // we're moving (dragging) 

次に、ドラッグとクリックを区別する方法を見つける必要があります。典型的なアプローチは、最初のクリック点から現在の点までの半径(長さ)を使用することです:外部の場合はドラッグ操作と見なします。

ので -

var radius = 9 * 9  // radius in pixels, 9 squared 
var firstPos;   // keep track of first position 

(私たちは、9を二乗しているので、我々は、後にすべてのマウス移動イベントの平方根を計算する必要はありません)。

その後、我々はこれらの事を考慮することは、当社のコールバックハンドラを定義することができます。

canvas.onmousedown = function(e) { 
    firstPos = getXY(e); // record click position (see getXY function in demo) 
    isDown = true;  // record mouse state 
    isMoving = false; // reset move state 
}; 

次のハンドラではなく、canvas要素自体のwindowオブジェクトに設定することができます。これにより、マウスボタンが押されている間、キャンバス要素の外側に移動することができます。私たちは他のコードが同様にサブスクライブすることができますので、ここでaddEventListener()を使用する必要があります。

window.addEventListener("mousemove", function(e) { 
    if (!isDown) return; // we will only act if mouse button is down 
    var pos = getXY(e); // get current mouse position 

    // calculate distance from click point to current point 
    var dx = firstPos.x - pos.x, 
     dy = firstPos.y - pos.y, 
     dist = dx * dx + dy * dy;  // skip square-root (see above) 

    if (dist >= radius) isMoving = true; // 10-4 we're on the move 

    if (isMoving) { 
    // handle move operation here 
    } 
}); 

そして最後に、我々は、クリックを検出だけでなく、windowオブジェクトにこのまた、マウスの状態を更新:

window.addEventListener("mouseup", function(e) { 
    if (!isDown) return; // no need for us in this case 
    isDown = false;  // record mouse state 

    if (!isMoving) { 
    // it was a click, handle click operation here 
    } 
}); 

最後の問題はウェイポイントをクリックすることです。絶対的なチェック(つまりx ===値)を行うと、その時点でマウスボタンを正確に配置する必要があるため、ほとんどOKになりません。ウェイポイント(ウェイポイントのオブジェクトwpを想定)の幅と高さを使用して範囲を許可:

if (pos.x >= wp.x && pos.x < wp.x + wp.width && 
    pos.y >= wp.y && pos.y < wp.y + wp.height) { ... } 

var ctx = canvas.getContext("2d"); 
 
var wp = {x: 50, y:50, width:12, height:12}; // demo way-point 
 
ctx.font = "20px sans-serif"; 
 
ctx.fillText("Click or click+move on this canvas...", 10, 30); 
 
ctx.strokeRect(wp.x, wp.y, wp.width, wp.height); 
 

 
var isDown = false;  // mouse button is held down 
 
var isMoving = false;  // we're moving (dragging) 
 
var radius = 9 * 9   // radius in pixels, 9 squared 
 
var firstPos;    // keep track of first position 
 

 
canvas.onmousedown = function(e) { 
 
    ctx.clearRect(0,0,canvas.width,canvas.height); 
 
    ctx.strokeRect(wp.x, wp.y, wp.width, wp.height); 
 
    
 
    firstPos = getXY(e); 
 
    isDown = true;   // record mouse state 
 
    isMoving = false;  // reset move state 
 
}; 
 

 
window.addEventListener("mousemove", function(e) { 
 
    if (!isDown) return;  // we will only act if mouse button is down 
 
    var pos = getXY(e);  // get current mouse position 
 

 
    // calculate distance from click point to current point 
 
    var dx = firstPos.x - pos.x, 
 
     dy = firstPos.y - pos.y, 
 
     dist = dx * dx + dy * dy;  // skip square-root (see above) 
 

 
    if (dist >= radius) isMoving = true; // 10-4 we're on the move 
 

 
    if (isMoving) { 
 
    ctx.clearRect(0,0,canvas.width,canvas.height); 
 
    ctx.strokeRect(wp.x, wp.y, wp.width, wp.height); 
 
    ctx.fillText("MOVING", 10, 30); 
 
    } 
 
}); 
 

 
window.addEventListener("mouseup", function(e) { 
 
    if (!isDown) return;  // no need for us in this case 
 
    isDown = false;   // record mouse state 
 

 
    if (!isMoving) { 
 
    if (firstPos.x >= wp.x && firstPos.x < wp.x + wp.width && 
 
     firstPos.y >= wp.y && firstPos.y < wp.y + wp.height) { 
 
     ctx.fillText("CLICKED WAYPOINT", 10, 30); 
 
    } 
 
    else { 
 
     ctx.fillText("CLICK", 10, 30); 
 
    } 
 
    } 
 
}); 
 

 
function getXY(e) { 
 
    var rect = canvas.getBoundingClientRect(); 
 
    return {x: e.clientX - rect.left, y: e.clientY - rect.top} 
 
}
canvas {background:#ccc}
<canvas id=canvas width=620 height=180></canvas>

+0

良い回答とデモ - いつものように。 :-) Upvote。この質問はかなり頻繁に聞かれるので、「なぜマウスクリスとドラッグが問題なのですか」についての序文を追加することを検討しますか?はいの場合は、質問が今後発生する場合は、ここであなたのQ&Aを「標準」と言います。乾杯! – markE

+1

@markEは私にとって良いようです。私はちょっと後で更新に戻ってきます。 – K3N

関連する問題