10、《每周一点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 < right){vx *= bounce;ball.x = ball.radius; }if(ball.y + ball.radius > bottom){vy *= bounce;ball.y = bottom - ball.radius;}else if(ball.y - ball.radius < top){vy *= bounce;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!现在来看看动画效果。
具体代码如下:
<p id="record">当前的速度为:</p><canvas id="canvas" width="1000" height="600" style="background:#000;">your browser not support canvas!</canvas><script src="../js/utils.js"></script><script src="../js/ball.js"></script><script>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, oldYvar 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和oldYoldX = 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);}()); }</script>
从动画中我们可以看出,当我们快速移动小球后,小球脱离鼠标后的运动速度很快。当我们缓慢移动的时候小球的移动速度很慢,由于我们定义的重力加速度比较大,你会看到小球快速的向下方坠落。在上方,我做了一个速度值得计算,来让效果更叫明显,可以直观的看到速度值得变化。
3.总结
本章主要学习了用户与canvas中的物体的交互,物体的移动,拖拽和抛扔。核心代码如下:
//得到球体坐标
Ball.prototype.getBounds = function(){return {x: this.x - this.radius,y: this.y - this.radius,width: this.radius*2,height: this.radius*2};
}
//捕获物体
utils.containsPoint = function(rect, x, y){return !(x<rect.x || x>rect.x + rect.width ||y<rect.y || y>rect.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
下一节,开始介绍高级动画,缓动动画和弹性动画,敬请期待!!!
10、《每周一点canvas动画》——移动物体(2)相关推荐
- 《每周一点canvas动画》——圆周运动
接<每周一点canvas动画>--波形运动 圆周运动可以分为两种基本的形式:正圆运动和椭圆运动. 在讲解圆周运动之前,必不可少的数学公式即将袭来.so,各位骚年们,请护好自己的膝盖.听不懂 ...
- 19、《每周一点canvas动画》——桌球运动(1)
每周一点canvas动画代码文件 一本好的技术书籍往往都是由浅入深,本系列文章基本上也遵循这个原理.在上一章中我们介绍了高级的坐标旋转,并且通过它,我们实现了任意角度的碰撞反弹效果,它让物体与非水平和 ...
- vpython 做圆周运动_《每周一点canvas动画》——圆周运动
接<每周一点canvas动画>--波形运动 圆周运动可以分为两种基本的形式:正圆运动和椭圆运动. 在讲解圆周运动之前,必不可少的数学公式即将袭来.so,各位骚年们,请护好自己的膝盖.听不懂 ...
- 7、《每周一点canvas动画》——边界检测与摩擦力(1)
本章已经是<Canvas 动画系列>动画的第七篇了,我保证这一章不会再有难的数学公式和物理概念.鉴于有的同学并不是从第一章开始看这个系列,我将会把本文所用到的一些 类文件 和 工具函数 文 ...
- 5、每周一点canvas动画--速度
查看全文 http://www.taodudu.cc/news/show-5250190.html 相关文章: 9个非常有趣的HTML5 Canvas动画特效合集 小程序直播-疯狂点赞Canvas动画 ...
- 17、《每周一点canvas动画》——星球守护
代码文件 在介绍完碰撞检测的内容后,总感觉不拿它做点什么事情有点虚啊!本章的内容应该在上周就更新完成,但是由于这几天实在比较忙.一直没空把这个小游戏的过程写出来,就一直拖到了现在.如题,我取了个比较炫 ...
- 11、《每周一点canvas动画》——缓动动画
本系列文章代码文件 前面的章节我们介绍了许多基本的动画,在本节我们将使用这些基本的动画来创建一些高级动画.今天我们介绍的第一个高级动画叫做缓动动画(ease),也许在写css动画的时候已经接触过 ea ...
- Canvas 动画引擎解析与微信小程序中的应用
点击观看大咖分享 抗击疫情,腾讯云在行动.在开发微信小程序的过程中,我们经常需要展现一些图形和图表.目前市面上有好几款常用的图形库,在这些图形库的底层都有渲染引擎在支撑. ZRender 是其中一款非 ...
- canvas动画3:交互
canvas动画3 时隔很久,本人终于又写博客了(重度拖延症),把之前留下的canvas交互动画讲一讲. 电脑上的交互,指的是鼠标和键盘,我们今天主要用的是鼠标. 既然是鼠标的话,就要获取鼠标的各种事 ...
最新文章
- Django博客系统(忘记密码)
- STL之Map和MFC之CMap比较学习
- Cs231n课堂内容记录-Lecture2-Part2 线性分类
- 从基于直方图的Graph-Cut到Grab-Cut
- Shell自动备份部署新项目
- 第一次c语言课程设计——学生选课管理系统
- 幅相频率特性曲线的绘制(1)
- mysql创建数据库sql语句_创建数据库的SQL语句:mysql数据库
- 区块链技术入门学习指引
- 不同形式弧微分的求解
- 两台计算机共享文件夹,两台电脑共享文件,详细教您两台电脑如何共享文件
- 外国人怎样看待Ubuntu麒麟?
- java如何输入(输出)二进制,八进制,十六进制数?(新手向)
- HTML+css制作简单游戏界面
- 清华校友、香港科技大学准博士ICCV顶会论文被爆公然抄袭!去年CVPR也是抄的...
- 四十三 iOS中UILabel部分字体颜色的修改
- 图像视频伪造检测,针对DeepFake技术检测效果不佳
- 抓包神器 Charles
- 2、通过mos管构成的逻辑门电路
- 支付宝服务器响应时间,APP接入支付宝支付完整流程及踩坑记录(含服务端)