## 移动物体 在第二章《用户交互》中,介绍过鼠标事件和触摸事件,可是到目前为止,我们用到鼠标事件和触摸事件还比较少,在本章中,我们将真正的进入交互动画中,主要介绍下面的内容: - 如何判断鼠标是否落在某一个物体上 - 拖曳物体 - 投掷物体 **1、鼠标事件和触摸事件** 在介绍三种交互动画前,我们先来回顾一下鼠标事件和触摸事件。 **1.1 鼠标事件** 要触发鼠标事件,当然得有触发它的设备,不能光用眼睛盯着屏幕, 而触发鼠标事件的设备当然是鼠标,它会检测自身的移动以及按钮是否单击,随后计算机会触发一系列的事情:追踪鼠标指针的位置,确定鼠标按钮被按下时指针的位置,计算鼠标的移动速度以及确定何时发生双击事件等等。 简单的来说,鼠标要做的事就是 单击 和 移动 。 单击事件又可分解为两个事件: 鼠标键按下 的事件及 按键弹起 的事件,大多数情况下,这两个事件是同时发生的,但鼠标要做的例外一个事 移动 时,在这两个事件之间还会多了一个事件: 按下、移动、再释放 。 在《用户交互》这一章曾经说过,我们无法捕捉到canvas上的任何绘制图形、线等,所以我们只能将事件绑定到canvas元素上,然后通过计算鼠标相对于canvas元素的坐标来判断鼠标落在哪个绘制到canvas上的物体上。 下面我们就来讲解一下如何判断鼠标是否落在某一个物体(比如前面我们多次绘制的ball)上。 还是用图来分析: ![](https://box.kancloud.cn/30443e64f33145e44701c6df368c1d9d_246x242.png) 如上图所示,一般情况下,当要检测鼠标是否落在物体上时,我们会将物体放置在一个矩形区域(图中的红框)内,该矩形区域也称为物体的边界,然后通过获取鼠标位置,判断是否落在矩形区域内即可。 当然,你要捕捉的物体必须有x、y、width与height属性(不管是直接获取还是计算得出),前面我们已经知道如何获取鼠标相对canvas的坐标了,接下来往tool对象中添加一个方法 containsPoint() ,该函数接受三个参数,第一个是物体(body)对象(包括x、y、width与height属性),第二个和第三个参数则分别代表鼠标位置,返回值为true或false,判断一个指定的坐标位置是否位于矩形边界内。 ``` tool.containsPoint = function(body, x, y){ return !(x < body.x || x > (body.x + body.width) || y < body.y || y > (body.y + body.height)); }; ``` containsPoint()方法返回false表示不在矩形边界内,否则在矩形边界内。 将物体包裹在一个矩形之内,这是我们大多数情况下采取的方法,如果你想更加精确,那就要进行更加精确的计算了,比如:物体是圆形,那你就要使用三角函数来计算鼠标位置和圆心的距离: ![](https://box.kancloud.cn/519ea4d8dcb3d65db3abeb5ecaac4b0b_238x242.png) ``` dx = point.x -body.x; dy = point.y - body.y; dist = Math.sqrt(dx*dx + dy*dy) if(dist < body.radius){ console.log('鼠标移到物体上'); } ``` 实例:canvas-demo/containsPoint.html **1.2 触摸事件** 捕获触摸事件与捕获鼠标事件并没有太大的区别,在tool.captureMT()方法中,我已经将触摸事件和鼠标事件封装在了一起。 与鼠标事件不同的是,要触发触摸事件的不是鼠标,而是手指、触摸笔等等,而且鼠标会一直都在,而手指却不是一直处在触摸状态,所以添加一个isPressed属性,用于判断屏幕上是否有手指在触摸。 ``` var isPressed = false; function touchstart(event){ isPressed = true; // }; function touchend(event){ isPressed = false; }; ``` **2、移动物体** **2.1. 拖曳物体** 拖曳物体其实就是通过不断更新物体的坐标位置使其追随鼠标指针的位置。 拖曳圆球看看:canvas-demo/drag.html 关键代码: ``` ball.x = event.point.x; ball.y = event.point.y; ``` **2.2 投掷物体** 投掷物体就是用鼠标选中一个物体,拖曳着它向某个方向移动,松开鼠标后,物体沿着拖曳的方向继续移动。 在投掷物体时,必须在拖曳物体的过程中计算物体的速度向量,并在释放物体时将这速度向量赋给物体。比如,如果你以每帧10个像素的速度向左拖曳小球,那么在你释放球时,它的速度向量应该是vx = -10。 那么如何计算出物体被拖曳时的速度向量,只需按照如下计算: ``` 速度向量 = 新的位置 - 旧的位置。 ``` 在动画中,我们以帧为单位,所以时间也可以说是帧数。在拖曳物体时,它会在每一帧拥有一个新的位置,用当前帧的位置减去上一帧的位置,就可以计算出这一帧所移动的距离,这也就是每帧移动像素的速度向量值。 实例:拖曳物体,然后松开鼠标看看效果:canvas-demo/hurl.html 关键代码: ``` ball.speed.x = ball.x - oldX; ball.speed.y = ball.y - oldY; oldX = ball.x; oldY = ball.y; ``` 用小球当前的x、y轴坐标分别减去oldX与oldY,从而获得小球当前的速度向量,并将它们保存在球的速度中,最后将oldX与oldY变量更新为小球当前的位置。 **总结** 在这一章中,我们进一步了解了动画中的交互行为。掌握上面这些内容,你就可以在动画中实现对物体的拖曳、释放以及投资。 到目前为止,《canvas动画包教不包会》系列已经进行了七章,分别介绍了用户交互、三角函数、速度与加速度、边界和摩擦力、移动物体,这些是动画的基础知识,要想轻松的实现丰富的动画,就必须好好掌握这些。