<canvas>是HTML5中新增加的一个元素,我们可以使用脚本(通常使用JavaScript)在上面绘制图形,就像个画布一样。我们可以用它来绘制图表、制作一些动画。默认大小为300px × 150px。
在<canvas>中绘制图形的方法中,isPointInPath()方法用于检测指定的点是否在绘制图形的路径中,存在返回ture,不存在返回false。
注:在代码部分,红色加粗部分是重点要注意的内容哦!
在矩形中
在画布上绘制一个空心矩形,然后指定一个点,如果这个点在矩形的路径中,矩形的颜色为蓝色,否则为黑色。为了能清楚的看到那个点在哪里,我们后面再画上两条灰色的线,交叉的位置就是我们指定的点:
1 <body> 2 <canvas id="drawEle"> 3 您的浏览器不支持该标签 4 </canvas> 5 <script> 6 var c = document.getElementById("drawEle"); 7 ctx = c.getContext("2d"); 8 9 //矩形 10 ctx.beginPath(); 11 ctx.rect(10,20,280,20); //绘制矩形区域 12 if(ctx.isPointInPath(50,25)) { //判断(50,25)是否在矩形路径中 13 ctx.strokeStyle = "#0000FF"; //在则矩形是蓝色 14 } 15 else { 16 ctx.strokeStyle = "#000000"; //不在则矩形是黑色 17 } 18 ctx.stroke(); 19 20 //绘制定位用的直线 21 ctx.beginPath(); 22 ctx.strokeStyle = "#CCCCCC"; 23 ctx.moveTo(50,0); 24 ctx.lineTo(50,150); 25 ctx.stroke(); 26 ctx.beginPath(); 27 ctx.moveTo(0,25); 28 ctx.lineTo(300,25); 29 ctx.stroke(); 30 </script> 31 </body>
运行效果如下:
可以看到,我们定位的点再矩形区域内部,矩形的颜色变成了蓝色,也就是说这个点的位置在矩形的路径中。
在弧/曲线区域中
那我们再arc()创建的弧/曲线区域中定位试试看。之后也是使用两条灰色线交叉定位我们判断的点:
1 <body> 2 <canvas id="drawEle"> 3 您的浏览器不支持该标签 4 </canvas> 5 <script> 6 var c = document.getElementById("drawEle"); 7 ctx = c.getContext("2d"); 8 9 //弧/曲线 10 ctx.beginPath(); 11 ctx.arc(150,75,50,0,1.5 * Math.PI); //绘制圆形区域 12 if(ctx.isPointInPath(170,55)) { //判断(170,55)是否在矩形路径中 13 ctx.strokeStyle = "#0000FF"; //在则曲线是蓝色 14 } 15 else { 16 ctx.strokeStyle = "#000000"; //不在则曲线是黑色 17 } 18 ctx.stroke(); 19 20 //绘制定位用的直线 21 ctx.beginPath(); 22 ctx.strokeStyle = "#CCCCCC"; 23 ctx.moveTo(170,0); 24 ctx.lineTo(170,150); 25 ctx.stroke(); 26 ctx.beginPath(); 27 ctx.moveTo(0,55); 28 ctx.lineTo(300,55); 29 ctx.stroke(); 30 </script> 31 </body>
运行效果如下:
哦,圆还是蓝色的,说明定位是在路径中的。。。不对,这样子看上去好像没有闭合啊,那我们给它填充一下颜色(换成fill()):
1 <body> 2 <canvas id="drawEle"> 3 您的浏览器不支持该标签 4 </canvas> 5 <script> 6 var c = document.getElementById("drawEle"); 7 ctx = c.getContext("2d"); 8 9 //弧/曲线 10 ctx.beginPath(); 11 ctx.arc(150,75,50,0,1.5 * Math.PI); //绘制圆形区域 12 if(ctx.isPointInPath(170,55)) { //判断(170,55)是否在矩形路径中 13 ctx.fillStyle = "#0000FF"; //在则曲线是蓝色 14 } 15 else { 16 ctx.fillStyle = "#000000"; //不在则曲线是黑色 17 } 18 ctx.fill(); 19 20 //绘制定位用的直线 21 ctx.beginPath(); 22 ctx.strokeStyle = "#CCCCCC"; 23 ctx.moveTo(170,0); 24 ctx.lineTo(170,150); 25 ctx.stroke(); 26 ctx.beginPath(); 27 ctx.moveTo(0,55); 28 ctx.lineTo(300,55); 29 ctx.stroke(); 30 </script> 31 </body>
嗯,是没有超过区域,那我们让超过区域看看
1 <body> 2 <canvas id="drawEle"> 3 您的浏览器不支持该标签 4 </canvas> 5 <script> 6 var c = document.getElementById("drawEle"); 7 ctx = c.getContext("2d"); 8 9 //弧/曲线 10 ctx.beginPath(); 11 ctx.arc(150,75,50,0,1.5 * Math.PI); //绘制圆形区域 12 if(ctx.isPointInPath(180,45)) { //判断(180,45)是否在矩形路径中 13 ctx.fillStyle = "#0000FF"; //在则曲线是蓝色 14 } 15 else { 16 ctx.fillStyle = "#000000"; //不在则曲线是黑色 17 } 18 ctx.fill(); 19 20 //绘制定位用的直线 21 ctx.beginPath(); 22 ctx.strokeStyle = "#CCCCCC"; 23 ctx.moveTo(180,0); 24 ctx.lineTo(180,150); 25 ctx.stroke(); 26 ctx.beginPath(); 27 ctx.moveTo(0,45); 28 ctx.lineTo(300,45); 29 ctx.stroke(); 30 </script> 31 </body>
变黑了,说明这个点不再路径中。
在直线中
接下来就到最简单的线条了。其实写这个笔记就是因为这个线条来着┑( ̄ ▽  ̄)┍
使用moveTo()和lineTo()结合,创建一根直线,定位点在路径中直线为蓝色,否则为黑色。使用一条灰色线交叉定位我们判断的点:
1 <body> 2 <canvas id="drawEle"> 3 您的浏览器不支持该标签 4 </canvas> 5 <script> 6 var c = document.getElementById("drawEle"); 7 ctx = c.getContext("2d"); 8 9 //直线 10 ctx.beginPath(); 11 ctx.moveTo(40,40); 12 ctx.lineTo(260,40); 13 if(ctx.isPointInPath(150,40)) { //判断(150,40)是否在矩形路径中 14 ctx.strokeStyle = "#0000FF"; //在则直线是蓝色 15 } 16 else { 17 ctx.strokeStyle = "#000000"; //不在则直线是黑色 18 } 19 ctx.stroke(); 20 21 //绘制定位用的直线 22 ctx.beginPath(); 23 ctx.strokeStyle = "#CCCCCC"; 24 ctx.moveTo(150,0); 25 ctx.lineTo(150,150); 26 ctx.stroke(); 27 </script> 28 </body>
欸,怎么是黑色的啊,我不是定位点的y轴和线条两个点的y轴都重合了么?
就是这个情况,定位点如果定位在使用moveTo()和lineTo()绘制的直线中间自动生成的线上,是会返回false的!
那把定位点完全重合moveTo()的点试试看:
1 <body> 2 <canvas id="drawEle"> 3 您的浏览器不支持该标签 4 </canvas> 5 <script> 6 var c = document.getElementById("drawEle"); 7 ctx = c.getContext("2d"); 8 9 //直线 10 ctx.beginPath(); 11 ctx.moveTo(40,40); 12 ctx.lineTo(260,40); 13 if(ctx.isPointInPath(40,40)) { //判断(40,40)是否在直线路径中 14 ctx.strokeStyle = "#0000FF"; //在则直线是蓝色 15 } 16 else { 17 ctx.strokeStyle = "#000000"; //不在则直线是黑色 18 } 19 ctx.stroke(); 20 21 //绘制定位用的直线 22 ctx.beginPath(); 23 ctx.strokeStyle = "#CCCCCC"; 24 ctx.moveTo(40,0); 25 ctx.lineTo(40,150); 26 ctx.stroke(); 27 </script> 28 </body>
蓝了,蓝了,它蓝了!
那接下来我们用moveTo()和lineTo()做一个闭合的图形康康,定位就设在一条边中间,用两条灰色的线条交叉标记我们定位的点:
1 <body> 2 <canvas id="drawEle"> 3 您的浏览器不支持该标签 4 </canvas> 5 <script> 6 var c = document.getElementById("drawEle"); 7 ctx = c.getContext("2d"); 8 9 //直线 10 ctx.beginPath(); 11 ctx.moveTo(40,40); 12 ctx.lineTo(260,40); 13 ctx.lineTo(260,130); 14 ctx.closePath(); 15 if(ctx.isPointInPath(150,40)) { //判断(150,40)是否在路径中 16 ctx.fillStyle = "#0000FF"; //在则直线是蓝色 17 } 18 else { 19 ctx.fillStyle = "#000000"; //不在则直线是黑色 20 } 21 ctx.fill(); 22 23 //绘制定位用的直线 24 ctx.beginPath(); 25 ctx.strokeStyle = "#CCCCCC"; 26 ctx.moveTo(150,0); 27 ctx.lineTo(150,150); 28 ctx.stroke(); 29 30 ctx.beginPath(); 31 ctx.moveTo(0,40); 32 ctx.lineTo(300,40); 33 ctx.stroke(); 34 </script> 35 </body>
这个区域这个时候是蓝的了。也就是说不是闭合区域的时候,moveTo()和lineTo()中的线条是不算在区域内的,得闭合后才算。(对于这个观点,其实我是觉得有点怪怪的,感觉这个观点应该是接近正确答案但它不是正确答案)
在加粗的直线末端中
假如线条宽度有20px,上面我们知道只有和路径点重合了才算,那加粗的线条还是和路径点重合了算还是路径点y轴(假设是横线,那么就当它是长方形吧,竖这的边上任意一点)也算,这也是刚刚突然想到的,试试看:
1 <body> 2 <canvas id="drawEle"> 3 您的浏览器不支持该标签 4 </canvas> 5 <script> 6 var c = document.getElementById("drawEle"); 7 ctx = c.getContext("2d"); 8 9 //直线 10 ctx.beginPath(); 11 ctx.moveTo(40,40); 12 ctx.lineTo(260,40); 13 ctx.lineWidth = 40; 14 if(ctx.isPointInPath(40,35)) { //判断(40,35)是否在矩形路径中 15 ctx.strokeStyle = "#0000FF"; //在则直线是蓝色 16 } 17 else { 18 ctx.strokeStyle = "#000000"; //不在则直线是黑色 19 } 20 ctx.stroke(); 21 22 //绘制定位用的直线 23 ctx.beginPath(); 24 ctx.lineWidth = 1; 25 ctx.strokeStyle = "#CCCCCC"; 26 ctx.moveTo(40,0); 27 ctx.lineTo(40,150); 28 ctx.stroke(); 29 30 ctx.beginPath(); 31 ctx.moveTo(0,35); 32 ctx.lineTo(300,35); 33 ctx.stroke(); 34 </script> 35 </body>
看起来还是得和路径点重合。
那加粗后闭合呢?
1 <body> 2 <canvas id="drawEle"> 3 您的浏览器不支持该标签 4 </canvas> 5 <script> 6 var c = document.getElementById("drawEle"); 7 ctx = c.getContext("2d"); 8 9 //直线 10 ctx.beginPath(); 11 ctx.moveTo(40,40); 12 ctx.lineTo(260,40); 13 ctx.lineTo(260,130); 14 ctx.closePath(); 15 ctx.lineWidth = 40; 16 if(ctx.isPointInPath(40,35)) { //判断(40,35)是否在矩形路径中 17 ctx.f = "#0000FF"; //在则直线是蓝色 18 } 19 else { 20 ctx.strokeStyle = "#000000"; //不在则直线是黑色 21 } 22 ctx.stroke(); 23 24 //绘制定位用的直线 25 ctx.beginPath(); 26 ctx.lineWidth = 1; 27 ctx.strokeStyle = "#CCCCCC"; 28 ctx.moveTo(40,0); 29 ctx.lineTo(40,150); 30 ctx.stroke(); 31 32 ctx.beginPath(); 33 ctx.moveTo(0,35); 34 ctx.lineTo(300,35); 35 ctx.stroke(); 36 </script> 37 </body>
没有区别,也就是说加粗的部分并不算在路径内。
参考资料:MDN - CanvasRenderingContext2D.isPointInPath() : https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/isPointInPath