如圖:

簡單說明下,每個點都可以連接,但是不能重復連接同一個點,當連接到最后一個點的時候,會自動連接第一個點(首尾相連)。
var canvas = document.querySelector('#canvas')
var ctx = canvas.getContext('2d')
畫點
使用數組保存點的位置,遍歷數組將點畫出來
1 var points = [{x: 300,y: 98, isConnect: false},{x: 217,y: 264, isConnect: false},{x: 295,y: 359, isConnect: false},{x: 372,y: 508, isConnect: false},{x: 511,y: 385, isConnect: false},{x: 497,y: 203, isConnect: false}] 2 3 function drawPoint () { 4 for (var i = 0, len = points.length; i < len; i++) { 5 ctx.save() 6 ctx.beginPath() 7 ctx.arc(points[i].x, points[i].y, 10, 0, 2 * Math.PI) 8 ctx.fill() 9 ctx.restore() 10 } 11 }
畫線
畫線這部分涉及到交互,所以我們需要添加事件,設置drawing,當點擊的時候才能開始畫線
1 var mouse = { //用來保存鼠標移動的位置 2 start: {x: 0, y: 0}, 3 end: {x: 0, y: 0} 4 } 5 var drawing = false; //判斷是否可以畫線 6 function drawLine (pos1, pos2) { 7 ctx.save() 8 ctx.beginPath() 9 ctx.moveTo(pos1.x, pos1.y) 10 ctx.lineTo(pos2.x, pos2.y) 11 ctx.stroke() 12 ctx.closePath() 13 ctx.restore() 14 } 15 16 canvas.addEventListener('mousedown', function(e) { 17 18 mouse.start.x = e.pageX 19 mouse.start.y = e.pageY 20 drawing = true 21 }) 22 23 canvas.addEventListener('mousemove', function(e) { 24 25 mouse.end.x = e.pageX 26 mouse.end.y = e.pageY 27 ctx.clearRect(0, 0, canvas.width, canvas.height) //清除畫布 28 29 if (drawing) { 30 drawLine(mouse.start, mouse.end) 31 } 32 33 })
“吸附”點
我們現在是可以在任意一點開始畫線,但是我們的需求是,靠近某個點才能開始畫線
怎么判斷靠近某個點呢?使用勾股定理,計算兩點的距離(一個點是原點, 另一個點是鼠標位置)小於一個值(dis)時,我們判定被這個點“吸附”了,然后開始畫線。
寫一個方法計算距離:
1 function distance (pos1, pos2) { 2 return Math.sqrt(Math.pow(pos1.x - pos2.x, 2) + Math.pow(pos1.y - pos2.y, 2)) 3 }
判斷是否被”吸附“, 並且”吸附“過的點不能再連接:
1 function adsorption (mouse) { 2 3 for (var i = 0, len = points.length; i < len; i++) { 4 5 if (!points[i].isConnect && distance(mouse, points[i]) <= dis) { 6 7 points[i].isConnect = true 8 drawing = true 9 10 } 11 12 } 13 } 14 ... 15 //修改下事件 16 // canvas.addEventListener('mousedown', function(e) { 17 18 // mouse.start.x = e.pageX 19 // mouse.start.y = e.pageY 20 21 // }) 22 23 canvas.addEventListener('mousemove', function(e) { 24 25 mouse.end.x = e.pageX 26 mouse.end.y = e.pageY 27 ctx.clearRect(0, 0, canvas.width, canvas.height) 28 adsorption(mouse.end) 29 drawPoint() 30 if (drawing) { 31 drawLine(mouse.start, mouse.end) 32 } 33 34 })
到這里,鼠標靠近點的時候,就可以畫線了,但是並不是我們預想的那樣,應該從點開始畫線
這是因為在drawLine傳值的是mouse.start,我們只需要把mouse.start換成點的位置就可以了,那么如何換成點的位置呢?
可以用一個數組保存連接過的點:
1 var savePoints = [] 2 ... 3 //修改adsorption 4 function adsorption (mouse) { 5 6 for (var i = 0, len = points.length; i < len; i++) { 7 8 if (!points[i].isConnect && distance(mouse, points[i]) <= dis) { 9 10 points[i].isConnect = true 11 drawing = true 12 savePoints.push(points[i]) 13 14 } 15 16 } 17 } 18 ... 19 //修改mouse事件 20 canvas.addEventListener('mousemove', function(e) { 21 22 ... 23 if (drawing) { 24 drawLine(savePoints[savePoints.length - 1], mouse.end) 25 } 26 27 })
我們發現每次靠近一個點的時候,都是從這個點開始連線的,之前連接的線並沒有畫出來,clearRect清除了之前連的線
可以利用保存過的點,把之前連過的線畫出來:
1 ... 2 function drawOldLine () { 3 for (var i = 0, len = savePoints.length - 1; i < len; i++) { 4 drawLine(savePoints[i], savePoints[i + 1]) 5 } 6 } 7 ... 8 //修改mousemove事件 9 ... 10 if (_this.drawing) { 11 12 ... 13 drawOldLine() 14 15 }
好了,我們可以看到,每個點都可以連接,跟我們預想的一樣,現在就差最后一步了
首尾相連,簡單的思路就是,保存過的數組savePoints里的第一個點和最后一個點連線:
1 function autoLine () { 2 ctx.clearRect(0, 0, canvas.width, canvas.height) 3 drawOldLine() 4 drawPoint() 5 drawLine(savePoints[savePoints.length - 1], savePoints[0]) 6 drawing = false 7 }
到這里,已經完成了連線功能。
大家可以嘗試一下封裝成插件,以后可以方便地使用以及拓展。
