canvas实现运动轨迹,canvas动态绘制轨迹
概要
工作以来,写过vue、react、正则性、算法、小程序等知识。但是我从来没有写过画布,因为我真的不会!
2018年,给自己定一个小目标:学习canvas,达到的效果是可以用canvas实现一些css3不容易实现的动画。
作为学习canvas的第一个成果,很多人刚接触canvas时做的第一个demo就是实现一个“时钟”。当然,我也悟出了一个,不过与其说这个,不如说一个更有趣更简单的事情。
鼠标按住绘制轨迹
需求
在画布上,初始状态下画布上什么都没有。现在,我想在画布上添加一个小的鼠标事件,并用鼠标在上面书写。具体效果就是把鼠标移动到画布上的任意一点,然后按住鼠标,移动鼠标位置,就可以开始写了!
原理
首先简单分析一下思路。首先我们需要一个画布,然后计算鼠标在画布上的位置,将onmousedown事件和onmousemove事件绑定到鼠标上,在移动过程中绘制路径。释放鼠标时,绘图完成。
这个想法虽然很简单,但是里面也有一些需要小技巧才能实现的地方。
1.您需要一个包含画布元素的html文件。
这是一幅宽800、高400的画布。为什么不写px?哦,我暂时不明白。画布文档推荐的。
!doctype HTML HTML class= no-js lang= zh Head meta charset= UTF-8 meta http-equiv= x-ua-compatible content= ie=edge title canvas learning/title meta name= description content= meta name= viewport content= width=device-width,initial-scale=1 link rel= manifest href= site . web manifest link rel= apple-touch-icon href= icon . png link rel=样式表确定当前环境是否支持canvas。
在main.js中,我们写了一个自执行函数,下面是兼容性判断的代码片段。“代码体”将是实现需求的核心。
(function(){ let the canvas=document . query selector( # the canvas )if(!theCanvas !TheCanvas.getContext) {//不兼容画布return false } else {//code body } })()3 .获取2d对象。
context=the canvas . get context( 2D )4。获取当前鼠标相对于画布的坐标。
为什么要得到这个坐标?因为鼠标默认是获取当前窗口的相对坐标,而canvas可以位于页面上的任何位置,所以需要计算才能获取真正的鼠标坐标。
获取鼠标相对于画布的真实坐标被封装到一个函数中。如果觉得抽象,可以在草稿纸上画个图,明白为什么要做这个操作。
一般可以是x-rect.left和y-rect.top但是为什么实际上是X-rect . left *(canvas . width/rect . width)?
Canvas.width/rect.width的意思是判断画布中存在的缩放行为,并找出缩放倍数。
ConstwindowTocanvas=(canvas,x,y)={//从窗口中获取canvas元素的一些属性。MDN上有解释让rect=canvas . getboundingclient()//x和y参数从窗口传入鼠标的坐标,然后减去窗口左侧和顶部到canvas的距离。return { x:x-rect . left *(canvas . width/rect . width),y:y-rect . top *(canvas . height/rect . height)} } 5。使用第4步中的工具函数,我们可以将鼠标事件添加到画布中!
先按onmousedown事件绑定鼠标,用moveTo画坐标起点。
thecanvas . onmousedown=function(e){//获取鼠标按下的点相对于画布的坐标。Ele=windowtocanvas(画布,e.clientx,e.clienty)//ES6的解构赋值let {x,y}=ele //绘制起点。Context.moveTo(x,y)}6。当您移动鼠标时,没有鼠标长按事件。你怎么能监控它?
这里使用的技巧是在onmousedown内部执行另一个onmousemove事件,以便您可以监视并按住鼠标并移动它。
thecanvas . onmousedown=function(e){//获取鼠标按下的点相对于画布的坐标。Ele=windowtocanvas(画布,e.clientx,e.clienty)//ES6的解构赋值let {x,y}=ele //绘制起点。Context.moveTo(x,y) //鼠标移动事件theCanvas.onmousemove=(e)={//移动时获取新的坐标位置,用lineTo记录当前坐标,然后stroke绘制从前一点到当前点的路径Letele=WindowTocanvas(The canvas,E.clientx,e.clienty) let {x,y}=elecontext.lineto (x,y) context.stroke ()}} 7 .释放鼠标时,不再绘制路径。
有什么方法可以阻止onmouseup事件中上面监控到的两个事件?方法还真不少。将onmousedown和onmousemove设置为null是其一。我在这里用了“开关”。IsAllowDrawLine设置为bool值,控制是否执行函数。有关详细信息,请参见下面的完整源代码。
源码
这里有三个文件,index.html,main.js和utils.js,使用es6的语法。我已经用parcle配置了开发环境,所以不会有错误。如果直接复制代码,运行过程中出现错误,在无法升级浏览器的情况下,可以将es6的语法改为es5。
1、index.html
上面已经展示过了,就不赘述了。
2、主网站
从“”导入{ windowToCanvas }。/utils (function(){ let the canvas=document . query selector(# the canvas )if(!theCanvas !the canvas . get context){ return false } else { let context=the canvas . get context( 2d )let isAllowDrawLine=false the canvas . onmousedown=function(e){ isAllowDrawLine=true let ele=windowToCanvas(the canvas,e.clientX,e.clientY) let { x,y }=ele context.moveTo(x,y)the canvas . onmousemove=(e)={ if(isAllowDrawLine){ let ele=windowToCanvas(the canvas,e
/* *获取鼠标在画布上的坐标* */constwindotecanvas=(canvas,x,y)={ let rect=canvas . getboundingclientrect()return { x:x-rect . left *(canvas . width/rect . width),y:y-rect . top *(canvas.height/rect.height)} } export { windowToCanvas }总结
这里有一个误解。我用canvas object绑定了事件theCanvas.onmouseup其实canvas不能绑定事件,但是真正绑定的是文档和窗口。但是因为浏览器会自动帮你判断和移交事件处理,所以完全不用担心。
这就是本文的全部内容。希望对大家的学习和支持有帮助。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。