2016-05-15 19 views
0

我正在嘗試使用HTML 5畫布編寫簡單的地圖。拖動鼠標移動地圖,然後單擊選擇最近的航點。但是,有一個問題。當我拖動鼠標時,當我釋放它時,仍然會收到點擊事件。只有在點擊時沒有移動的情況下,我纔想知道。檢測點擊與HTML 5畫布上的拖動

我試圖檢查在鼠標移動事件處理程序沒有運動事件,但沒有成功:

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 
}; 

下一個處理程序可以在window對象,而不是canvas元素本身進行設置。這允許我們在保持鼠標按鈕的同時移動畫布元素。我們需要使用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。由於這個問題經常被問到,你會考慮在你的答案中增加一個前言:「爲什麼鼠標點擊與拖動是一個問題」*?如果是的話,那麼在將來問題出現時,我會在這裏將你的問答稱爲「規範」。乾杯! – markE

+1

@markE聽起來不錯。我稍後再回來更新。 – K3N