现实世界中万千万物都有其独自的运行轨迹,例如直线、圆、螺旋和复杂的贝塞尔曲线。今天我们一起来学习一下如何用 Canvas
实现最平凡的直线运动。Canvas
画图基础知识可参考 w3school 在线教程 。
一、矢量移动
要想为图像设置动画效果,可以采用每次为对象绘制不同的 x
坐标和 y
坐标,然后在每一帧中调用显示更新图像的函数即可。初始化起始点代码如下:
1 | var p1 = {x:20,y:20}; //初始点坐标 |
在两点之间移动很方便,但是很多时候并没有一个要移到哪里去的目标点,只有从哪里开始的起始点。这种情况下,创建一个 vector
作为移动对象就非常有用了。
矢量是一个具有数量和方向的物理量。数量就是对象移动的速度 speed
的值,方向就是对象移动的角度 angle
的值。现在,将对象移动的角度 angle
的值(方向)设为 45°
,在数学上,平滑直线通常代表角度为 0
,45°
的矢量就意味着向右下方移动。
弧度 radians
是度量角度的标准单位,大部分数学计算都需要将角度转换为弧度才能使用。将角度转为弧度,使用标准方程式 radians = angle * Math.PI/180
即可。代码如下:
1 | var angle = 45; //角度 |
计算对象沿矢量运动时的坐标值,请看下面简略2D坐标图:
可以看出,余弦通常与 x
值有关,正弦通常与 y
值有关,可以利用 sin
和 cos
来计算对象沿矢量的移动。代码如下:
1 | var speed = 5; //速度 |
在渲染画布 drawScreen()
函数中,将 ball.x
和 ball.y
分别加上 xunits
和 yunits
,即可随时更新小球位置坐标点。
drawScreen()
函数详细如下:
1 | //渲染画布 |
框架 javascript
代码如下:
1 | window.addEventListener('load',eventWindowLoaded,false); |
html
代码如下:
1 | <div style="position:absolute;top:50px;left:50px;"> |
最终实现效果如下:
二、多球撞墙反弹
尽管创建一个有数量、有方向的矢量并让对象沿着它精确移动看起来很有动画感,但是现实中却很少出现类似的运动。大部分时候,人们会希望这个对象能对周围的世界有反应,例如撞上水平或者垂直的墙后能弹回来。
根据第一小节的学习,我们知道一个球如何沿矢量运动,那么多球撞墙反弹需要解决两个问题,分别是多球沿矢量运动和如何反弹。
第一个问题:多球沿矢量运动
为实现多球应用程序,需要创建一个新的对象来控制关于每个反弹球的所有相关信息:x、y、 radius、speed、angle、radians、xunits、yunits
。这里假设我们要创建100个这样的随机小球,给予不同的速度,半径和矢量,如果用代码表示,即:
1 | //定义球数量 |
第二个问题:如何反弹
为了更好理解反弹动画,先来看一个简单的物理原理。这条原理经常用于光线上,但对于动画2D形状也非常有用,特别是对象撞上水平或垂直的墙反弹的情况。这个原理就是 反射角原理,即入射角等于反射角。
入射角是对象撞墙时的角度,反射角是对象从墙面反弹回来的角度。如下图所示:
由此可知,反弹角 = 180 - 入射角
。
javascript
代码如下:
1 | // ball.x 代表小球 x 坐标 ball.y 代表小球 y 坐标 |
updateBall(ball)
函数详细如下:
1 | function updateBall(ball){ |
到这里,主要代码已经全部给出,最终实现的效果如图: