《每周一点canvas动画》——移动物体(2)
本系列文章代码文件
在上一节《每周一点canvas动画》——移动物体(1)中我们介绍了如何捕获一个物体,并且对物体进行拖拽。首先,我们在小球的原型对象上添加了一个方法getBounds(),该方法的作用是返回一个对象,该对象内包含小球的坐标和长宽属性值,并且在我们的工具函数utils.js中也添加了一个方法containPoints(rect, x, y),该方法传入3个参数:对象rect,坐标x和y,返回一个布尔值用于判定我们的鼠标是否点击在了小球上。
然后,我们为canvas添加监听事件,当鼠标点击到了小球上时,判定为小球被鼠标捕获,这时如果你移动鼠标小球就会随着鼠标的位置而移动,当鼠标抬起移除监听事件,小球不再随鼠标移动,这样就完成了我们移动物体的目的。这一节我们主要介绍:
运动物体的捕获
物体的抛扔
总结
1.运动物体的捕获
在上一节中我们知道了,如何移动一个物体。那么,这一节我们更深入些,首先就来探讨如何捕获一个运动的物体。不过总体的思路还是沿用上一节已经搭建好的框架,我们所要做的就是发挥我们的想象力。。。
现在我们理一下要完成这个动画需要做哪些事情。
既然是捕获运动中的物体,那么一定要让我们的小球动起来。这个很容易,前面的章节都介绍过了,我们只需要让小球的坐标值加上其速度值就好了,如果你想更逼真一些,就加个加速度或者再来个摩擦力。
为了方便起见我们必须设置边界,避免小球超出canvas消失不见。
我们必须设置一个开关变量来保证当鼠标点击在了小球上,小球不再做自由运动,而改由跟随鼠标做运动。
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.radius2
};
}
//捕获物体
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
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!