实现canvas连线
Posted zhongxk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现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 }
画线
画线这部分涉及到交互,所以我们需要添加事件,设置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 }
到这里,已经完成了连线功能。
大家可以尝试一下封装成插件,以后可以方便地使用以及拓展。
以上是关于实现canvas连线的主要内容,如果未能解决你的问题,请参考以下文章
自己定义View时,用到Paint Canvas的一些温故,简单的帧动画(动画一 ,"掏粪男孩Gif"顺便再提提onWindowFocusChanged)(代码片段