2013-09-23 49 views
3

我想在HTML5畫布上拖放路徑。
我沒有發現像SVG提供事件的東西,如果我們點擊形狀。
任何人都知道我可以在這裏處理路徑項目上的事件嗎?我想這樣做沒有任何Java腳本庫。HTML5在沒有JS庫的情況下在畫布上拖放路徑

以下是我當前的代碼繪製路徑:

var canvas = document.getElementById("html5Canvas"); 
var context = canvas.getContext("2d"); 
var drawing = false; 

canvas.addEventListener("mousedown", startDraw, false); 
canvas.addEventListener("mousemove", continueDraw, false); 
canvas.addEventListener("mouseup", endDraw, false 


function startDraw(event) 
{ 
    drawing = true; 
    context.moveTo(event.clientX, event.clientY);  
} 

function continueDraw(event) 
{ 
    if (drawing) 
    { 
     context.lineTo(event.clientX, event.clientY);  
     context.stroke();  
    } 
} 

function endDraw(event) 
{ 
    if (drawing) 
    { 
     context.lineTo(event.clientX, event.clientY);  
     context.stroke();  
     drawing = false; 
    } 
} 

感謝。

+0

冷杉矩形我們可以檢測到點擊,但是如果我們有線並且它們是交集如何檢測哪個線條被點擊? – Narando

+0

重建路徑(不繪製它),然後使用isPointInStroke()方法。對於下一個形狀重複步驟。該方法可能需要在某些瀏覽器中添加前綴。在未來,Path將提供給我們,使事情變得更容易一些,但現在我們需要爲每次檢查重新構建全局路徑。另請參閱:http://stackoverflow.com/questions/17268596/an-old-quesition-how-to-determine-a-point-in-a-irregular-shape – K3N

回答

12

籌備工作

爲了檢測線路點擊,我們需要記錄所有路徑信息。

以下示例是原始帖子中提供的代碼的修改版本,其中包括一個筆畫記錄器,用於將每個筆畫(鼠標向下和鼠標向下)記錄到包含所有筆畫的數組。

爲了簡單起見,我們在這裏傾聽鼠標點擊時,我們改變模式。在點擊模式下,我們迭代筆畫集合並重新構建之前記錄的路徑,然後檢查我們的鼠標位置是否位於這些行中的某一行。

的代碼可以通過使用建立的路徑之前命中區域,以減少開銷,但對於演示的目的僅被包括在基本碼進行優化:

演示代碼

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

即使是複雜的重疊線可以毫無問題地檢測:

Demo snapshot

(是的,我知道!我可以在任何一天擊敗Dali和Munch!)

相關問題