Javascript动画效果的实现(二)

在上一篇文章我们具体的介绍了Javascript中动画效果的实现原理。并重点了介绍了两种判断动画完成的情况。如果你没看过,请点击这里查看。这篇文章我们不是介绍如何制作动画,二是介绍如何让你做得动画更加的自然,让人看起来更加的自然和舒服,这里主要介绍一下在动画过程中经常用到的缓动效果,本篇文章假设你对高中物理有一定的理解,当然要是对数学物理方法有所涉猎的话就更好了:P,不过这不是必须的。(ps.虽然数学物理方法是我的主修课,但是我学的还是一塌糊涂)

文章中介绍的两种方法分别为:1,结束位置;2,持续时间。我们在网页中用到最多的主要是第二种方法,我们在上篇文章中以匀速直线运动为例子介绍了第二种情况下如何得到当前位置的运算公式,以及我们公式中的变量所代表的意义。当然这是最简单的,也是处于理想情况下才会得到的一个公式。这里我们不再讲述如何得到的这个公式以及如何使用这个公式的了(因为上一篇文章中已经讲过了)。

如果你运行过上一个例子后你会觉得那个动画效果非常的不自然,为什么呢?因为自然界中我们日常的生活中基本上是不会碰到匀速直线的运动的,这就好比我们在看机械舞的时候会觉得跳舞的人动作很滑稽不自然,因为他们就是在试图模仿匀速的运动。我们的例子中红色的方块一开始没有经过加速就以一个恒定的速度运动,然后结束的时候又突然结束,所以我们肯定会觉得不自然。

我们在看到物体的运动的时候,大脑会不由自主的分析其受力情况,会考虑它为什么会动,以及它何时会停下来。我们这里说的缓动也就是运动过程中速度受加速度影响的过程,这个加速度可能是正的或者是负的,其正负的不同会体现在运动是加速运动还是减速运动,也就是是缓入还是缓出。

我们再分析一下我们的例子,看看它在正常的基本符合实际情况下它是如何运动的。假设红色的方块是冰面上的一个箱子,我们现在要让箱子运动起来。红色的方块开始的时候肯定是静止在那不动的,它要动起来我们就必须推它一把,然后它就开始运动了,这里我们再把情况简化一下,冰面的摩擦力很小,所以我们假设摩擦力足够小,小到可以忽略,而且我们推动它的力是一个恒定不变的力,这就是一个匀加速直线运动。

根据我们学过的匀加速运动物理公式:
s = v0t + (1/2)a*t*t(这里在页面中,上标和下标的现实确实不方便,大家凑合着看吧:P)
根据这个公式我们可以计算出我们动画过程中运动物体当前的位置。

当前时间为t,路程的改变值为c,持续的时间为d,初始位置为b,根据我们刚才分析的情况,初始位置和初始速度都为0,将我们的变量带入到公式中得到:
c = (1/2)a*d*d=>a=2c/(d*d)
从而得到我们当前的位置p为:
p=((1/2)*2c/(d*d)*(t*t)+b=c*t*t/(d*d)
将我们获得的式子利用程序的特性进一步简化:
p=c*(t/=d)*t

推导示意图

推导示意图

不知道你看明白了吗?我们现在将一个匀加速直线运动的方程式转换成我们在做动画时用到的是根据时间获取位置的公式。其实很简单,就是将现成的的公式简单的转换一下,变得我们程序中可以用,这是匀加速直线运动,也就是缓入,匀减速直线运动也就是缓出也是同样的道理这里就不推导了。

其实到这里你会说匀加速直线运动也是一种理想的情况,现实中也不会存在的。对,确实,现实中也不会存在匀加速直线运动,我们可能还要考虑摩擦力,空气阻力以及动力的不稳定等等……但是它看起来比匀速直线运动自然多了不是吗?而且我们也不需要那么复杂的模型,我们只是为了用Javascript实现一个相对来说比较自然的效果不是嘛?cloudgamer写过的一片文章《JavaScript Tween算法及缓动效果》中直观的介绍了各种缓动效果,比如更高次的缓动,正弦缓动等等效果,这里我就不再赘述了,他的那篇文章写的非常好,在这里也要感谢一下他,从他的blog我学习到了很多东西。

我们利用我们刚才推导出的公式举一个简单的例子,还是用上一篇文章的例子,只是将其中的匀速直线运动的公式换成二次缓动的公式:

  1. var obj=document.getElementById('mydiv');
  2. var t=0,c=500,d=40,b=0;
  3. function nowPosition(t,c,d,b){
  4. oreturn c*(t/=d)*t+b;
  5. o//return c*t/d+b;
  6. }
  7. function changeStyle(){
  8. oobj.style.left = nowPosition(t,c,d,b)+'px';
  9. ot++;
  10. oif(t<=d)
  11. osetTimeout(changeStyle,20);
  12. }
  13. changeStyle();

别忘了给页面加上那个红色的方块……

  1. <DIV style="POSITION: absolute; WIDTH: 50px; BACKGROUND: #f00; HEIGHT: 50px; LEFT:0px" id=mydiv></DIV>

你可以把代码拷到页面中运行,记得要把Javascript代码写在Div对象的后面或者将javascript代码放到window.onload方法中。或者你可以直接点击我做好的Demo页面查看效果。

这里简单的讲述了一个Javascript中缓动效果的实现,是对Javascript动画效果(一)的一个简单的补充,让我们能够做出更加自然的效果,相信大家都是精益求精的不是吗?接下来我还会写一下如何实现一个更加通用的动画对象,让我们使用面向对象的手法,建立一个可以简单方便使用动画对象。有什么写的不对或者不恰当的地方欢迎您批评指正,欢迎交流!

转载请注明原文出处《Javascript动画效果的实现(二)》 如无特别声明,所有文章均遵守创作共用 署名-非商业-禁止演绎 3.0协议。

13条回复 发表于 “Javascript动画效果的实现(二)”上

  1. mahoe says:

    这两篇关于 Javascript动画效果的实现
    很有启发性, 让人一种豁然开朗的感觉, 非常感谢

    [回复]

    DK 说:

    @mahoe, 非常高兴对你有所帮助~

    [回复]

  2. 哦辉 says:

    学习了,

    [回复]

  3. says:

    javascript实现动态效果测试

    ovar obj=document.getElementById(‘mydiv’);
    var t=0,c=500,d=40,b=0;
    function nowPosition(t,c,d,b){
    return c*(t/=d)*t+b;
    //return c*t/d+b;
    }
    function changeStyle(){
    obj.style.left = nowPosition(t,c,d,b)+’px’;
    t++;
    if(t<=d)
    setTimeout(changeStyle,20);
    }
    changeStyle();

    为什么我的这个代码实现不起来呢?
    直接运行你页面的代码能动起来的,但是我改成我的就动不起来了呢?

    [回复]

    DK 说:

    @花, 自己对比一下,看看是否有什么地方写错了

    [回复]

  4. 不知 says:

    楼主,偶能问个问题吗:

    o$(function()
    o{
    ovar t=0,b=0,c=500,d=30;
    o
    ofunction rel()
    o{
    o//var obj = t*c/d+b+’px’;
    ovar obj = c*(t/=d)*t+b+’px’;
    o$(“#red”).css(“left”,obj);
    o
    oif(t<=d){setTimeout(rel,40); t++;}
    o}
    orel();
    o})

    为什么这样不行呢?不调用函数就不行吗?

    [回复]

    DK 说:

    @不知, 跟函数没有关系,你这个不能用吗?

    [回复]

  5. […] 将easeInQuad用函数表达出来就是:currentValue = changValue*(currentTime/duration) + beginValue,其中只有currentTime是变量,那么这就是一个二次式,也是传说中的抛物线。二次方缓动模拟的是一种匀加速运动,推导公式如下: (盗用了别人一幅图 ,查看原文) […]

  6. 深蓝 says:

    这篇文章有点难理解,数学物理一点都不懂..
    加我QQ好吗?真心求教.QQ67068205

    [回复]

  7. 乌拉拉 says:

    博主 还是我哈! 新手哦,不要嫌麻烦!嘻嘻
    p=c*(t/=d)*t 这个完全看不懂~ 是啥意思哦。麻烦博主解释下o!

    [回复]

    DK 说:

    @乌拉拉, 这句代码可能有点绕,不过算是基础的知识。

    文中有讲到:
    c*t*t/(d*d) === c*(t/=d)*t

    右边的式子只是根据程序运行的特性对左边进行简化处理后的结果而已。

    c * (t = t/d) * t(注意执行的此处时的t已经是以前的t/d了),还有什么不明白的吗?如果还有不清楚可发邮件给我。

    [回复]

  8. […] Javascript动画效果的实现(二) […]

我要评论