《每周一点canvas动画》——移动物体(2)

本系列文章代码文件

在上一节《每周一点canvas动画》——移动物体(1)中我们介绍了如何捕获一个物体,并且对物体进行拖拽。首先,我们在小球的原型对象上添加了一个方法getBounds(),该方法的作用是返回一个对象,该对象内包含小球的坐标和长宽属性值,并且在我们的工具函数utils.js中也添加了一个方法containPoints(rect, x, y),该方法传入3个参数:对象rect,坐标x和y,返回一个布尔值用于判定我们的鼠标是否点击在了小球上。

然后,我们为canvas添加监听事件,当鼠标点击到了小球上时,判定为小球被鼠标捕获,这时如果你移动鼠标小球就会随着鼠标的位置而移动,当鼠标抬起移除监听事件,小球不再随鼠标移动,这样就完成了我们移动物体的目的。这一节我们主要介绍:

  1. 运动物体的捕获

  2. 物体的抛扔

  3. 总结

1.运动物体的捕获

在上一节中我们知道了,如何移动一个物体。那么,这一节我们更深入些,首先就来探讨如何捕获一个运动的物体。不过总体的思路还是沿用上一节已经搭建好的框架,我们所要做的就是发挥我们的想象力。。。

现在我们理一下要完成这个动画需要做哪些事情。

  1. 既然是捕获运动中的物体,那么一定要让我们的小球动起来。这个很容易,前面的章节都介绍过了,我们只需要让小球的坐标值加上其速度值就好了,如果你想更逼真一些,就加个加速度或者再来个摩擦力。

  2. 为了方便起见我们必须设置边界,避免小球超出canvas消失不见。

  3. 我们必须设置一个开关变量来保证当鼠标点击在了小球上,小球不再做自由运动,而改由跟随鼠标做运动。

ok,现在我们来做代码上的实现!首先是前两步:

//定义函数moveAndBoun
function moveAndBoun(){
var left = canvas.width,
right = 0,
top = 0,
bottom = canvas.height;

           //让小球动起来           ball.x += vx;           vy += gravity;           ball.y += vy;           //边界检测           if(ball.x + ball.radius > left){               vx *= bounce;               ball.x = left - ball.radius;           }else if(ball.x - ball.radius  bottom){               vy *= bounce;               ball.y = bottom - ball.radius;           }else if(ball.y - ball.radius 

我们把让小球运动和边界检测放到了一个函数里。这样很方便通过开关变量来调用。

第三步定义开关变量,并在动画循环中调用它,用来控制小球是自用运动还是跟随鼠标一起运动。当鼠标按下时isMousedown变为true,抬起是变为false。

var isMousedown = false;

(function drawFrame(){
window.requestAnimationFrame(drawFrame, canvas);
context.clearRect(0, 0, canvas.width, canvas.height);

            //如果没有捕获则自由运动           if(!isMouseDown){               checkBoundries();           }           ball.draw(context);       }());

现在让我们来看看动画效果

完整的代码我已经托管到了gitHub上,你可以通过点击文章开头的链接获取。注意动画中,我有一个尝试扔小球的动作,但是它并没有按我们所想象的那样呈抛物线飞出去,这是因为当鼠标抬起时我们设定了小球的水平速度(vx)为零,只有纵向的速度与加速度,所以这里我们要做个简单的改进,来达到让小球飞出去的效果。

2.物体的抛扔

物体的抛扔在动画中怎样描述呢?它意味着你点击一个物体并且以一定的方向开始移动它,当你释放它时,物体沿着你拖拽的方向继续移动,是不是跟我们平时扔东西一模一样。

那么当小球扔出去后,它的运行速度怎么计算呢?你可以直接在水平方向重新给它设定一个速度(vx),甚至你也可以设置竖直方向的速度(vy),这样当你释放一个小球的时候,它就会按照你新设定的速度运动。但是,这有一个问题,那就是绝对的不真实。想想你平时扔一个东西,物体脱离你手后的运行速度是根据你在扔这个物体的时间段内,物体运动的距离决定的。换言之,也就是说你扔的越快,物体脱离你手后运动的速度就越快。

在canvas中,物体的位置变化由速度决定,即 oldPosition + velocity = newPosition。稍做变形,就可以得出velocity = newPosition - oldPosition,这样我们就得出了物体释放时的运行的速度。

这里有几个比较关键的点必须说明,什么时候算是oldPosition,什么时候算是newPosition。当你拖动一个物体,物体在每一帧都会有一个newPosition,而oldPosition就是物体在上一帧的位置。如果你使用requesstAnimationFrame()方法做动画循环,每一帧的时间间隔会不一样,不过基本上都是在十几毫秒左右,你的oldPosition就是十几毫秒前(也就是上一帧)的位置,newPosition就是十几毫秒后(下一帧)的位置。现在清楚了吧!

看看我们给的公式,不难发现,速度的大小取决于在一帧中运动的距离,也就是新位置与旧的位置之间的差值。这样就跟我们现实中完全一样了。

ok!现在来看看动画效果。

具体代码如下:

当前的速度为:

   your browser not support canvas!       window.onload = function(){       var canvas = document.getElementById('canvas'),           oP = document.getElementById('record'),           context = canvas.getContext('2d'),           ball = new Ball(30, "orange"),           vx = Math.random()*10 + 5,           vy = -10,           bounce = -0.8,           gravity = 1.8,           speed, //speed 用于记录速度值           oldX, oldY; //定义变量oldX, oldY       var isMouseDown = false,           mouse = utils.captureMouse(canvas),           w = 0, h = 0;           ball.x = canvas.width/2;           ball.y = canvas.height/2;                  canvas.addEventListener("mousedown", function(event){           if(utils.containsPoint(ball.getBounds(), mouse.x, mouse.y)){               w = mouse.x - ball.x;               h = mouse.y - ball.y;              //如果点击到了小球上,那么分别将小球的位置赋值给oldX, oldY              //并且随着小球的移动oldX和oldY每一帧都在刷新               oldX = ball.x;               oldY = ball.y;               isMouseDown = true;               canvas.addEventListener('mouseup', onMouseUp ,false);               canvas.addEventListener('mousemove', onMouseMove, false);           }       }, false);       function onMouseUp(e){...}       function onMouseMove(e){...}                  function moveAndBoun(){...}       //计算抛出速度       function trackVelocity(){              //用当前小球的位置减去上一帧的坐标           vx = ball.x - oldX;           vy = ball.y - oldY;           //重新赋予oldX和oldY           oldX = ball.x;           oldY = ball.y;           speed = Math.sqrt(vx*vx + vy*vy);           oP.innerHTML = "当前的速度为:"+speed.toFixed();       }       (function drawFrame(){           ...           //调用           if(!isMouseDown){               checkBoundries();           }else{               trackVelocity();           }           ball.draw(context);       }());               }

从动画中我们可以看出,当我们快速移动小球后,小球脱离鼠标后的运动速度很快。当我们缓慢移动的时候小球的移动速度很慢,由于我们定义的重力加速度比较大,你会看到小球快速的向下方坠落。在上方,我做了一个速度值得计算,来让效果更叫明显,可以直观的看到速度值得变化。

3.总结

本章主要学习了用户与canvas中的物体的交互,物体的移动,拖拽和抛扔。核心代码如下:

//得到球体坐标
Ball.prototype.getBounds = function(){
return {
x: this.x - this.radius,
y: this.y - this.radius,
width: this.radius2,
height: this.radius
2
};
}
//捕获物体
utils.containsPoint = function(rect, x, y){
return !(xrect.x + rect.width ||
yrect.y + rect.height);
}

//物体的移动拖拽
canvas.addEventListener("mousedown", function(event){
if(utils.containsPoint(ball.getBounds(), mouse.x, mouse.y)){
...
canvas.addEventListener('mouseup', onMouseUp ,false);
canvas.addEventListener('mousemove', onMouseMove, false);
}
}, false);

//理解物体的抛扔的概念
vx = ball.x - oldX;
vy = ball.y - oldY
下一节,开始介绍高级动画,缓动动画和弹性动画,敬请期待!!!

关键字:JavaScript, html5, canvas


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部