實現canvas連線


如圖:

簡單說明下,每個點都可以連接,但是不能重復連接同一個點,當連接到最后一個點的時候,會自動連接第一個點(首尾相連)。

 

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 }
View Code

畫線

畫線這部分涉及到交互,所以我們需要添加事件,設置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 }

到這里,已經完成了連線功能。

大家可以嘗試一下封裝成插件,以后可以方便地使用以及拓展。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM