籌備工作
爲了檢測線路點擊,我們需要記錄所有路徑信息。
以下示例是原始帖子中提供的代碼的修改版本,其中包括一個筆畫記錄器,用於將每個筆畫(鼠標向下和鼠標向下)記錄到包含所有筆畫的數組。
爲了簡單起見,我們在這裏傾聽鼠標點擊時,我們改變模式。在點擊模式下,我們迭代筆畫集合並重新構建之前記錄的路徑,然後檢查我們的鼠標位置是否位於這些行中的某一行。
的代碼可以通過使用建立的路徑之前命中區域,以減少開銷,但對於演示的目的僅被包括在基本碼進行優化:
演示代碼
ONLINE DEMO HERE
爲了記錄,我們需要有東西來存儲行/筆劃:
var lines = [], line;
我們添加了一個事件偵聽器,用於在切換模式時使用的點擊。請注意,通常你會分享鼠標按下/上事件也許不是:
canvas.addEventListener("click", checkLine, false);
爲了讓線條更加「點擊」,我們用較粗的線在這裏的寬度(固定演示):
context.lineWidth = 3;
爲了記錄我們需要修改現有的回調。還有一個錯誤,它會導致每條鼠標移動時線條被重新繪製,如果線條很長,最終會減慢繪圖的速度。
我們還需要調整鼠標的位置,使其成爲相對帆布:
function startDraw(event) {
/// if we are in "click" mode exit from here (for demo)
if (mode.checked === true) return;
/// adjust mouse position
var pos = mouseXY(canvas, event);
drawing = true;
/// start a new path
context.beginPath();
context.moveTo(pos.x, pos.y);
/// create a new stroke and push first position to it
line = [];
line.push([pos.x, pos.y]);
}
對於我們得出我們需要重新設置路徑,所以我們不重繪整條生產線(在每個部分的最終渲染/重繪你當然會僅僅重繪一氣呵成的線條,但不能同時提請吧):
function continueDraw(event) {
if (drawing) {
/// adjust mouse position
var pos = mouseXY(canvas, event);
/// complete one line segment started in mouse down
context.lineTo(pos.x, pos.y);
context.stroke();
/// reset path and start from where we ended this line
context.beginPath();
context.moveTo(pos.x, pos.y);
/// store current point to stroke/line
line.push([pos.x, pos.y]);
}
}
最後當線完成後,我們保存我們的行程:
function endDraw(event) {
if (drawing) {
var pos = mouseXY(canvas, event);
context.lineTo(pos.x, pos.y);
context.stroke();
drawing = false;
/// push stroke/line to line stack
lines.push(line);
}
}
我們用它來調整鼠標的位置::
function mouseXY(c, e) {
var r = c.getBoundingClientRect();
return {x: e.clientX - r.left, y: e.clientY - r.top};
}
檢查線點擊
要檢查,我們需要通過我們的網上收集來迭代重建每一行的路徑線。沒有必要繪製這些路徑,所以速度是確定的。當一個路徑被重建,我們通過使用isPointInStroke
檢查對路徑的調整鼠標的位置:
function checkLine(e) {
if (mode.checked === false) return;
var i = 0, line, l, p, pos = mouseXY(canvas, e);
/// make sure stroke has same width as originally recorded
context.lineWidth = 3;
/// loop through line collection
for(; line = lines[i]; i++) {
/// reset path
context.beginPath();
/// begin stroke
context.moveTo(line[0][0], line[0][1]);
/// iterate through each point stored
for(l = 1; p = line[l]; l++) {
/// add a line
context.lineTo(p[0], p[1]);
}
/// then we check the point
if (context.isPointInStroke(pos.x, pos.y) === true) {
alert('hit line ' + i); /// show "ID" of line clicked
return;
}
}
}
即使是複雜的重疊線可以毫無問題地檢測:
(是的,我知道!我可以在任何一天擊敗Dali和Munch!)
冷杉矩形我們可以檢測到點擊,但是如果我們有線並且它們是交集如何檢測哪個線條被點擊? – Narando
重建路徑(不繪製它),然後使用isPointInStroke()方法。對於下一個形狀重複步驟。該方法可能需要在某些瀏覽器中添加前綴。在未來,Path將提供給我們,使事情變得更容易一些,但現在我們需要爲每次檢查重新構建全局路徑。另請參閱:http://stackoverflow.com/questions/17268596/an-old-quesition-how-to-determine-a-point-in-a-irregular-shape – K3N