Canvas实战---模仿GOOGLE浮动小球效果
来源:互联网 发布:安卓刷机软件哪个最好 编辑:程序博客网 时间:2024/04/30 19:27
看到基于Canvas动画的Google浮动小球效果,非常炫,决定自己尝试模仿着做一个。
Demo:http://qs20199.github.io/SuspendingBall/
这个Demo并不难,包含以下两个部分
- 物理控制
- 动画控制
物理控制
function Ball(posX,posY,color,radius){ this.iOriginX=this.iCurX=posX; this.iOriginY=this.iCurY=posY; this.sColor=color; this.iRadius=radius; this.iDX=this.iDY=0;}
- OriginX/Y代表小球的原始位置
- CurX/Y代表小球的实际位置。
- dx和dy代表了小球在两个方向上的速度
小球控制有以下逻辑
- 每一帧小球将移动dx/dy个像素
//移动aBalls[i].iCurX+=aBalls[i].iDX;aBalls[i].iCurY+=aBalls[i].iDY;
- 当小球碰到墙时将反弹
if((aBalls[i].iCurX<=0+aBalls[i].iRadius)) { aBalls[i].iCurX=aBalls[i].iRadius+1; aBalls[i].iDX=-aBalls[i].iDX;}if((aBalls[i].iCurX >=oCanvas.width-aBalls[i].iRadius)) { aBalls[i].iCurX=oCanvas.width-aBalls[i].iRadius-1; aBalls[i].iDX=-aBalls[i].iDX;}if(aBalls[i].iCurY<=0+aBalls[i].iRadius) { aBalls[i].iCurY=aBalls[i].iRadius+1; aBalls[i].iDY=-aBalls[i].iDY;}if(aBalls[i].iCurY >=oCanvas.height-aBalls[i].iRadius) { aBalls[i].iCurY=oCanvas.height-aBalls[i].iRadius-1; aBalls[i].iDY=-aBalls[i].iDY;}
- 引力(加速度)控制
- 原始位置对小球有吸引力
- 鼠标对小球具有排斥力
- 存在与移动方向相反的阻力
//速度控制if(oMousePos.x!=""){ //有鼠标,存在引力和斥力 var Dis=Math.pow(Math.pow(aBalls[i].iCurX-oMousePos.x,2)+Math.pow(aBalls[i].iCurY-oMousePos.y,2),0.5); aBalls[i].iDX+=0.003*(aBalls[i].iOriginX-aBalls[i].iCurX)+20/Math.pow(Dis,1.8)*(aBalls[i].iCurX-oMousePos.x); aBalls[i].iDY+=0.003*(aBalls[i].iOriginY-aBalls[i].iCurY)+20/Math.pow(Dis,1.8)*(aBalls[i].iCurY-oMousePos.y);}else{ //无鼠标,只存在引力 aBalls[i].iDX+=0.003*(aBalls[i].iOriginX-aBalls[i].iCurX); aBalls[i].iDY+=0.003*(aBalls[i].iOriginY-aBalls[i].iCurY);}//限制最大速度if(aBalls[i].iDX>MaxSpeed) aBalls[i].iDX=MaxSpeed;if(aBalls[i].iDX<-MaxSpeed) aBalls[i].iDX=-MaxSpeed;if(aBalls[i].iDY>MaxSpeed) aBalls[i].iDY=MaxSpeed;if(aBalls[i].iDY<-MaxSpeed) aBalls[i].iDY=-MaxSpeed;//阻力aBalls[i].iDX*=0.98;aBalls[i].iDY*=0.98;
以上物理控制流程包含在了updateBalls()函数里,而这个函数并不实际进行动画,只是对象属性。
实际上计算公式并没有硬性规定,公式不同自然会有不同的运动效果,大家可以自己研究。
动画控制
动画采用requestAnimationFrame,而没有采用定时器(实测前者的流畅度将远超后者)。关于requestAnimationFrame,网上已经有了很详尽的资料,在此不在赘述。
function draw() { updateBalls(); oContext.clearRect(0,0,oCanvas.width,oCanvas.height); oContext.fillText("by QS",800,260); for(var i=aBalls.length-1;i>=0;i--){ oContext.beginPath(); oContext.arc(aBalls[i].iCurX,aBalls[i].iCurY,aBalls[i].iRadius,0,2*Math.PI); oContext.fillStyle=aBalls[i].sColor; oContext.fill(); } requestAnimFrame(draw);};
注意遍历每个球的时候,首先要beginPath(),否则球将会连接在一起。
以上是这个demo的核心部分。
写的过程中遇到了以下几个问题
撞墙检测
由于位置的变化不是连续的(即dx/dy会大于1),因此总有可能让小球直接穿过墙壁。试了几种算法,都不能很好的解决这个问题,后来读了Google小球的源码,发现他的处理方式是:只要到了区域范围以外,就将位置坐标强制设为临界值(而非在基础上加dx/dy)。这么说可能表述不清楚,看代码就清楚了:
if((aBalls[i].iCurX<=0+aBalls[i].iRadius)) { aBalls[i].iCurX=aBalls[i].iRadius+1; aBalls[i].iDX=-aBalls[i].iDX;}
阻力
一开始没有考虑到阻力,于是小球最后在原始位置附近徘徊,后来想起高中学的动量守恒,就想起来阻力这回事了。
aBalls[i].iDX*=0.98;aBalls[i].iDY*=0.98;
0 0
- Canvas实战---模仿GOOGLE浮动小球效果
- canvas动态小球重叠效果
- canvas动态小球重叠效果
- canvas动态小球重叠效果
- 模仿google导航效果
- 仿ASSISTIVETOUCH效果的浮动层小球
- Canvas绘制平抛小球效果
- JavaScript实现小球运动撞击效果,模仿气泡屏保
- HTML5 Canvas实战之刮奖效果
- HTML5 Canvas实战之刮奖效果
- HTML5 Canvas实战之刮奖效果
- canvas-小球跳动
- canvas躁动的小球
- 模仿google首页图片动画效果 (css+javascript)
- 粗略模仿google+圈子拖拽效果 ----- JQUERY特效模板
- [模仿]canvas视频拼图
- canvas例子一弹跳小球
- Canvas绘制页面小球跳动
- python中timeit模块用法
- 获取元素节点(DOM基础 )
- 昨天在微信里看到的一篇文章,应该不算是个新闻,但是还是值得仔细读一下。特别是对于那些在一个公司干了很多年却没有发展,或者每年跳槽两三次的同学确实应该反思看一看。原文地址 以下是正文 我曾经带过一个
- 20150225学习笔记
- adb命令、adb shell与Linux各种命令
- Canvas实战---模仿GOOGLE浮动小球效果
- opencv 霍夫变换检测直线
- linux学习基础杂记
- 2015年,除了阿里和腾讯,我们还能不能聊点别的?
- 工厂模式
- *LeetCode-Rotate Array
- 3Swift\OC\Java中字符串的比较
- Java异常处理新特性
- Android项目工程目录详解