本系列文章代码文件

在上一节《每周一点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 < 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)相关推荐

  1. 《每周一点canvas动画》——圆周运动

    接<每周一点canvas动画>--波形运动 圆周运动可以分为两种基本的形式:正圆运动和椭圆运动. 在讲解圆周运动之前,必不可少的数学公式即将袭来.so,各位骚年们,请护好自己的膝盖.听不懂 ...

  2. 19、《每周一点canvas动画》——桌球运动(1)

    每周一点canvas动画代码文件 一本好的技术书籍往往都是由浅入深,本系列文章基本上也遵循这个原理.在上一章中我们介绍了高级的坐标旋转,并且通过它,我们实现了任意角度的碰撞反弹效果,它让物体与非水平和 ...

  3. vpython 做圆周运动_《每周一点canvas动画》——圆周运动

    接<每周一点canvas动画>--波形运动 圆周运动可以分为两种基本的形式:正圆运动和椭圆运动. 在讲解圆周运动之前,必不可少的数学公式即将袭来.so,各位骚年们,请护好自己的膝盖.听不懂 ...

  4. 7、《每周一点canvas动画》——边界检测与摩擦力(1)

    本章已经是<Canvas 动画系列>动画的第七篇了,我保证这一章不会再有难的数学公式和物理概念.鉴于有的同学并不是从第一章开始看这个系列,我将会把本文所用到的一些 类文件 和 工具函数 文 ...

  5. 5、每周一点canvas动画--速度

    查看全文 http://www.taodudu.cc/news/show-5250190.html 相关文章: 9个非常有趣的HTML5 Canvas动画特效合集 小程序直播-疯狂点赞Canvas动画 ...

  6. 17、《每周一点canvas动画》——星球守护

    代码文件 在介绍完碰撞检测的内容后,总感觉不拿它做点什么事情有点虚啊!本章的内容应该在上周就更新完成,但是由于这几天实在比较忙.一直没空把这个小游戏的过程写出来,就一直拖到了现在.如题,我取了个比较炫 ...

  7. 11、《每周一点canvas动画》——缓动动画

    本系列文章代码文件 前面的章节我们介绍了许多基本的动画,在本节我们将使用这些基本的动画来创建一些高级动画.今天我们介绍的第一个高级动画叫做缓动动画(ease),也许在写css动画的时候已经接触过 ea ...

  8. Canvas 动画引擎解析与微信小程序中的应用

    点击观看大咖分享 抗击疫情,腾讯云在行动.在开发微信小程序的过程中,我们经常需要展现一些图形和图表.目前市面上有好几款常用的图形库,在这些图形库的底层都有渲染引擎在支撑. ZRender 是其中一款非 ...

  9. canvas动画3:交互

    canvas动画3 时隔很久,本人终于又写博客了(重度拖延症),把之前留下的canvas交互动画讲一讲. 电脑上的交互,指的是鼠标和键盘,我们今天主要用的是鼠标. 既然是鼠标的话,就要获取鼠标的各种事 ...

最新文章

  1. Django博客系统(忘记密码)
  2. STL之Map和MFC之CMap比较学习
  3. Cs231n课堂内容记录-Lecture2-Part2 线性分类
  4. 从基于直方图的Graph-Cut到Grab-Cut
  5. Shell自动备份部署新项目
  6. 第一次c语言课程设计——学生选课管理系统
  7. 幅相频率特性曲线的绘制(1)
  8. mysql创建数据库sql语句_创建数据库的SQL语句:mysql数据库
  9. 区块链技术入门学习指引
  10. 不同形式弧微分的求解
  11. 两台计算机共享文件夹,两台电脑共享文件,详细教您两台电脑如何共享文件
  12. 外国人怎样看待Ubuntu麒麟?
  13. java如何输入(输出)二进制,八进制,十六进制数?(新手向)
  14. HTML+css制作简单游戏界面
  15. 清华校友、香港科技大学准博士ICCV顶会论文被爆公然抄袭!去年CVPR也是抄的...
  16. 四十三 iOS中UILabel部分字体颜色的修改
  17. 图像视频伪造检测,针对DeepFake技术检测效果不佳
  18. 抓包神器 Charles
  19. 2、通过mos管构成的逻辑门电路
  20. 支付宝服务器响应时间,APP接入支付宝支付完整流程及踩坑记录(含服务端)

热门文章

  1. 开机后,电脑显示屏无信号怎么办?
  2. 江南爱软装十大品牌 软装与硬装还是有区别的
  3. 如何使用jQuery获取文本框值
  4. 关于竞业协议的一些问题
  5. 事业环境因素和组织过程资产区别
  6. 责任链模式在王者荣耀中的应用,妙啊!
  7. word 当前页插入页眉、页脚、页码。要求奇偶页眉不同,而页码连续。
  8. 21年执业药师考试备考四大有效记忆方法
  9. 我学习到的一些保险知识
  10. Wiley:International Journal for Numerical Methods in Biomedical Engineering投稿流程