接着上一篇文章,基于参考文献,继续学习在Canvas中实现物体抛掷,为了不使物体一直运动下去,程序中还增加了重力及反弹损耗的影响。
物体抛掷的逻辑是用户用鼠标拖拽物体,拖拽一段距离后松开鼠标,而后物体根据惯性移动,受重力、反弹消耗及四周边界的限制,物体最终停止移动。在此过程中主要包括以下功能点:
- 物体捕获:该功能参照上一篇文章即可实现;
- 物体拖拽:同样参考上一篇文章实现;
- 物体加速度:在物体拖拽过程中,通过计算当前帧和上一帧中的物体圆心位置差值而来,包括x方向和y方向的加速度;
- 边界限制:物体移动过程中(不论是拖拽还是自由运动)不能超出边界范围,主要通过计算物体的圆心、半径及Canvas的边界值得出;
- 松开鼠标后的物体速度:通过综合计算物体加速度、重力和反弹损耗得出。
程序的关键代码如下所示(主要借鉴自参考文献):
var cnv=$$("canvas");
var cxt=cnv.getContext("2d");
var mouse=tools.getMouse(cnv);
...
...
var ballX=cnv.width/2;
var ballY=cnv.height/2;
var ballR=20;
var isMouseDown=false;
...
var oldballX,oldballY;//记录上一帧中的物体圆心位置
var vx=0,vy=0;//记录物体x、y方向的加速度
var gravity=1.5;//重力值
var bounce=-0.8;//反弹消耗系数
...
...
cnv.addEventListener("mousedown",function()
{
if(window.tools.CheckMouse(mouse,ballX,ballY,ballR))
{
isMouseDown=true;
oldballX=ballX;
oldballY=ballY;
...
...
txt.innerHTML="捕获成功";
}
else
{
txt.innerHTML="";
}
},false);
function onMouseUp()
{
isMouseDown=false;
...
...
}
(function frame()
{
window.requestAnimationFrame(frame);
cxt.clearRect(0,0,cnv.width,cnv.height);
if(isMouseDown)//拖拽物体运动
{
//计算加速度
vx=ballX-oldballX;
vy=ballY-oldballY;
//记录本帧中的圆心位置
oldballX=ballX;
oldballY=ballY;
}
else//物体自由运动
{
vy+=gravity;
ballX+=vx;
ballY+=vy;
//边界限制,同时反弹时基于反弹消耗系数降低加速度
if(ballX<ballR)
{
ballX=ballR;
vx=vx*bounce;
}
else if(ballX>cnv.width-ballR)
{
ballX=cnv.width-ballR;
vx=vx*bounce;
}
if(ballY<ballR)
{
ballY=ballR;
vy=vy*bounce;;
}
else if(ballY>cnv.height-ballR)
{
ballY=cnv.height-ballR;
vy=vy*bounce;;
}
}
...
...
})();
物体抛掷效果如下所示:
参考文献:
[1]从0到1 HTML5 Canvas动画开发