有关Canvas的一点小事--鼠标绘图
1、 如何根据鼠标位置获取canvas上对应位置的x,y。
2、 canvas的图糊了,设置宽和高的方式不对。
3、鼠标绘图代码
之前听说过canvas这个元素,但是实际上并没有深入了解过。不过日前有个项目一是使用canvas显示dicom格式的医疗影像,一是利用canvas元素生成图像压缩包,将之前对canvas隐隐约约的好奇心被无限放大,那就尝试做一个用鼠标绘制图像的画布吧。这不难,网上一搜都是教程,然而……很多事情好像并不像想象的美好。
要做的很简单,mousedown的时候设置开始作画的标签,开始作画后就开始捕捉mousemove的轨迹来作画,mouseup的时候停止(后面附完整代码)。
1、 如何根据鼠标位置获取canvas上对应位置的x,y
然而,无论使用offsetX,offsetY还是clientX-canvas.width,clientY-canvas.height都获取不到对应的x,y,我甚至找不到鼠标落下的点和鼠标位置的任何关系。我知道这应该跟canvas的拉伸有关,之前就有遇到过需要调整canvas大小后图像出问题的问题,然而网上很多代码都是直接使用这两个值,都是大忽悠,但是我对canvas没有一点了解,完全不知道如何转换,幸亏后来找到合适的方法。
var c=document.getElementById("myCanvas"); var ctx=c.getContext("2d"); //********尝试获得对应位置的x,y c.addEventListener('click',function(event){ var event = event||window.event; var bbox = c.getBoundingClientRect(); var x = event.offsetX * (c.width / bbox.width); var y = event.offsetY * (c.height / bbox.height);
ctx.beginPath(); ctx.arc(x,y,10,0,2*Math.PI); ctx.stroke(); });
2、 图糊了,如何设置宽和高。
一开始我是把canvas当作普通元素处理,那么设置宽和高不就是,:
#myCanvas{
width:800px;
height:600px;
}
然后图糊了,下图不太明显,但是在网页中的确不能看。
然后我就知道了canvas要设置的是像素值,不是简单的宽和高,设置方法有下面两种:
<1>行内设置属性
<canvas id="myCanvas" width="800" height="500"></canvas>
<2>js设置属性
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
c.width=800;
c.height=600;
3、鼠标绘图代码
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"/> <script src='js/jquery-3.3.1.min.js'></script> <style> body{ background:black; text-align:center; } #myCanvas{ margin:10px auto; background:white; } </style> </head> <body> <canvas id="myCanvas"></canvas> <script type="text/javascript"> $(document).ready(function(){ var c=document.getElementById("myCanvas"); var ctx=c.getContext("2d"); c.width=800; c.height=600; var tempx = -1, tempy = -1; function painting(event){ var event = event||window.event; /*获取宽和高*/ var bbox = c.getBoundingClientRect(); var x = event.offsetX * (c.width / bbox.width); var y = event.offsetY * (c.height / bbox.height); /*画线*/ ctx.beginPath(); ctx.moveTo(tempx, tempy); ctx.lineTo(x, y); ctx.stroke(); ctx.closePath(); /*存值*/ tempx = x; tempy = y; } c.onmousedown = function(event){ var event = event||window.event; var bbox = c.getBoundingClientRect(); /*存初值*/ tempx=event.offsetX * (c.width / bbox.width); tempy=event.offsetY * (c.height / bbox.height); /*开始作画*/ c.onmousemove = painting; }; c.onmouseup = function(event){ c.onmousemove = null; }; }); /********* **********/ </script> </body> </html>
还可以做:
1、shift绘制图像直线,根据shiftKey绘制,下有实现,不过不太灵敏,不够符合理想的状态
2、橡皮擦,和清除全部图像,使用
context.clearRect(0, 0, canvas.width, canvas.height);
3、画圆画矩形,拖动会更改大小,这个涉及的细节更多了
圆形:
ctx.beginPath();
ctx.arc(95,50,40,0,2*Math.PI);
ctx.stroke();
矩形:
ctx.fillRect(0,0,150,75);
4、设置颜色选择、更改画笔粗细(可以使用正方形代替线,不过好像不太对劲)
ctx.fillStyle="#FF0000";
5、添加文字
ctx.font="30px Arial";
ctx.fillText("Hello World",10,50);
6、历史画笔,返回恢复
保存好进行过的操作
7、保存下载图片
下文再进行讨论
这些事件要考虑的细节问题太多,就懒得写代码调整尝试了,下面是添加了shift操作并做了一些优化的代码
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"/> <script src='js/jquery-3.3.1.min.js'></script> <style> body{ background:black; text-align:center; } #myCanvas{ margin:10px auto; background:white; } </style> </head> <body> <canvas id="myCanvas"></canvas> <script type="text/javascript"> $(document).ready(function(){ var c=document.getElementById("myCanvas"); var ctx=c.getContext("2d"); c.width=800; c.height=600; var tempx = -1, tempy = -1; var shiftline=-1.0,shiftx=-1,shifty=-1;/*shift画直线,因为x,y太快捕捉不到角度,另起一个shiftx,shifty来储存*/ //*******用鼠标画线 function paintingLine(event){ var event = event||window.event; //*******获取宽和高 var bbox = c.getBoundingClientRect(); var x = event.offsetX * (c.width / bbox.width); var y = event.offsetY * (c.height / bbox.height); //********shift var shiftKey = event.shiftKey; if(shiftKey==true){ if(shiftline==-1.0){ if(shiftx==-1){ shiftx = tempx; shifty = tempy; } if(timer==3){ if(x-shiftx==0){ shiftline = -2.0; } else{ shiftline = (y-shifty)*1.0/(x-shiftx); } } timer = timer+1; } else{ if(shiftline==-2.0){ x = 0; } else{ y = shifty+(x-shiftx) * shiftline; } } } else{ shiftline = -1.0; shiftx = -1; shifty = -1; timer = 0; } //**********画线 ctx.beginPath(); ctx.moveTo(tempx, tempy); ctx.lineTo(x, y); ctx.stroke(); ctx.closePath(); //**********存值 tempx = x; tempy = y; } //******按下鼠标开始画线 c.onmousedown = function(event){ var event = event||window.event; var bbox = c.getBoundingClientRect(); //*********存初值 tempx=event.offsetX * (c.width / bbox.width); tempy=event.offsetY * (c.height / bbox.height); //*******开始作画 c.onmousemove = paintingLine; }; //**********松开鼠标键停止作画 c.onmouseup = function(event){ c.onmousemove = null; shiftline = -1.0; shiftx = -1; shifty = -1; timer = 0; }; //**********离开界面停止作画 c.onmouseout = function(event){ c.onmousemove = null; shiftline = -1.0; shiftx = -1; shifty = -1; timer = 0; }; }); /********* 还可以做: 1、shift绘制图像直线,根据shiftKey绘制,上面有实现,不过不太灵敏,不够符合理想的状态 2、橡皮擦,和清除全部图像,使用 context.clearRect(0, 0, canvas.width, canvas.height); 3、画圆画矩形,拖动会更改大小,这个涉及的细节更多了 圆形: ctx.beginPath(); ctx.arc(95,50,40,0,2*Math.PI); ctx.stroke(); 矩形: ctx.fillRect(0,0,150,75); 4、设置颜色选择、更改画笔粗细(可以使用正方形代替线,不过好像不太对劲) ctx.fillStyle="#FF0000"; 5、添加文字 ctx.font="30px Arial"; ctx.fillText("Hello World",10,50); 6、历史画笔,返回恢复 保存好进行过的操作 7、保存下载图片 下文再进行讨论 这些事件要考虑的细节问题太多,就懒得写代码调整尝试了 **********/ </script> </body> </html>
参考:
获取鼠标位置和canvas的对应xy:https://blog.csdn.net/u010513756/article/details/47363743