Flash 做动画时会用到 Tween 类,利用它可以做很多动画效果,例如缓动、弹簧等等。我这里要教大家的是怎么利用 Flash 的 Tween 类的算法,来做js的Tween算法,并利用它做一些简单的缓动效果。

实例效果:

 
 
 

Tween类型:
Linear Quadratic Cubic Quartic Quintic Sinusoidal
Exponential Circular Elastic Back Bounce

ease类型:
easeIn easeOut easeInOut

效果说明

首先大家到这里下载flash的as脚本(建议看看这里的demo),1.0和2.0都可以(里面的算法都一样)。
例如打开2.0的可以看到几个as文件,每个文件对应一个Tween效果,分别有(参考里面的说明):
Linear:无缓动效果;
Quadratic:二次方的缓动(t^2);
Cubic:三次方的缓动(t^3);
Quartic:四次方的缓动(t^4);
Quintic:五次方的缓动(t^5);
Sinusoidal:正弦曲线的缓动(sin(t));
Exponential:指数曲线的缓动(2^t);
Circular:圆形曲线的缓动(sqrt(1-t^2));
Elastic:指数衰减的正弦曲线缓动;
Back:超过范围的三次方缓动((s+1)*t^3 - s*t^2);
Bounce:指数衰减的反弹缓动。
ps:以上都是自己的烂翻译,希望各位修正。

每个效果都分三个缓动方式(方法),分别是:
easeIn:从0开始加速的缓动;
easeOut:减速到0的缓动;
easeInOut:前半段从0开始加速,后半段减速到0的缓动。
其中Linear是无缓动效果,没有以上效果。

然后看看里面的算法,以Quad.as的easeOut为例:

Code
static function easeOut (t:Number, b:Number, c:Number, d:Number):Number {
    return -c *(t/=d)*(t-2) + b;
}

这是as代码,四个参数分别是:
t: current time(当前时间);
b: beginning value(初始值);
c: change in value(变化量);
d: duration(持续时间)。
ps:Elastic和Back有其他可选参数,里面都有说明。

那如何在js中利用这些算法呢?可以看到,虽然是as代码,但里面的程序是可以直接放在js里使用的。
我们可以定义一个类,把它这部分放在里面:

Code
var Tween = {
    Quad: {
        easeOut: function(t,b,c,d){
            return -c *(t/=d)*(t-2) + b;
        }
    }
}

这样,就可以用Tween.Quad.easeOut取得这个算法了,其他算法也一样处理就行了。

接下来就可以利用这个js的Tween来做一些缓动效果了。
先通过上面的坐标实例说一下算法原理:
x轴是时间,y轴是当前值,b是y轴的初始值,x轴的初始值是0,t是当前时间。当t(x轴)逐渐增加到达d时,当前值(y轴)会到达目标值(b+c)。
想详细理解的话可以找资料看看吧(貌似跟数学关系比较大)。

下面就介绍如何使用这个Tween了,首先b、c、d三个参数(即初始值,变化量,持续时间)在缓动开始前,是需要先确定好的。
举一个简单的例子,一个div要向右缓动,left初始值是50,那么b就是50,要向右移动100,那c就是100,如果知道的是目标值,例如要向右移动到150,那就把目标值150减初始值b就是变化量c了。
至于d的设置就比较灵活,只要符合t是从0向d递增(或递减)就可以了。
d跟步长配合使用来设置持续时间,例如d设置为100,如果设置步长是1,那么从0到100就有100步,即分100次来完成这个过程,步数越多那么持续时间就越长。
至于t的变化相当于时间的变化,一般是均匀变化的,每次变化都增加一个步长,当t从0递增(或递减)到d时,缓动就结束了。
要注意的是t是从0开始的,设置步长时必须确定t确实能到达d,如果上面的步长是3,那么t就永远都到不了d了。更好的处理是当t等于或超过d之后,就停止定时器并设置当前值为目标值。

了解了Tween的使用后就可以实现动画效果了。继续上面的例子,已经确定b是50,c是100,d是100,步长是1,使用Tween.Quad.easeOut算法。那么可以用以下程序实现缓动:

Code
var b=,c=,d=,t=;
function Run(){
    div.style.left = Math.ceil(Tween.Quad.easeOut(t,b,c,d)) + "px";
    if(t<d){ t++; setTimeout(Run, ); }
}
Run();

一个简单的缓动效果就实现了,要实现不同的缓动,只需要使用对应的Tween算法就行了,以前看来遥不可及的效果,现在这么容易就实现了(当然那些算法才是最难的地方)。

这样关于缓动的效果就介绍完了,但其实远远不止这些,我们还可以自己定义一些算法,发挥想象力,做一些好玩的效果。

 
 
Code
<input id="idClick" type="button" value="click">
<div id="test1" style="position:absolute;width:5px;height:5px;background:#333; font-size:0;"></div> <div id="test2" style="position:absolute;width:5px;height:5px;background:#F00; font-size:0;"></div>
<script>
var Round = {
    X: function(t,b,r){ return r*Math.cos(t/20)+b; },
    Y: function(t,b,r){ return r*Math.sin(t/20)+b; }
} var t=x=y=0; document.getElementById("idClick").onclick = function(e){
    document.onmousemove = function(e){
        e=e||event;
        x=e.clientX+document.documentElement.scrollLeft;
        y=e.clientY+document.documentElement.scrollTop;
    };
    document.onmousemove(e);
    setInterval(function(){
        var iX = Math.ceil(Round.X(t,x,100)), iY = Math.ceil(Round.Y(t,y,50));
        with(document.getElementById("test1").style){ left = iX + "px"; top = iY + "px"; }
        with(document.getElementById("test2").style){
            left = Math.ceil(Round.X(t*5,iX,25)) + "px"; top = Math.ceil(Round.Y(t*5,iY,25)) + "px";
        }
        t++;
    }, 10);
}
</script>

完整Tween

Code
var Tween = {
    Linear: function(t,b,c,d){ return c*t/d + b; },
    Quad: {
        easeIn: function(t,b,c,d){
            return c*(t/=d)*t + b;
        },
        easeOut: function(t,b,c,d){
            return -c *(t/=d)*(t-2) + b;
        },
        easeInOut: function(t,b,c,d){
            if ((t/=d/) < ) return c/2*t*t + b;
            return -c/2 * ((--t)*(t-2) - 1) + b;
        }
    },
    Cubic: {
        easeIn: function(t,b,c,d){
            return c*(t/=d)*t*t + b;
        },
        easeOut: function(t,b,c,d){
            return c*((t=t/d-1)*t*t + 1) + b;
        },
        easeInOut: function(t,b,c,d){
            if ((t/=d/) < ) return c/2*t*t*t + b;
            return c/2*((t-=2)*t*t + 2) + b;
        }
    },
    Quart: {
        easeIn: function(t,b,c,d){
            return c*(t/=d)*t*t*t + b;
        },
        easeOut: function(t,b,c,d){
            return -c * ((t=t/d-1)*t*t*t - 1) + b;
        },
        easeInOut: function(t,b,c,d){
            if ((t/=d/) < ) return c/2*t*t*t*t + b;
            return -c/2 * ((t-=2)*t*t*t - 2) + b;
        }
    },
    Quint: {
        easeIn: function(t,b,c,d){
            return c*(t/=d)*t*t*t*t + b;
        },
        easeOut: function(t,b,c,d){
            return c*((t=t/d-1)*t*t*t*t + 1) + b;
        },
        easeInOut: function(t,b,c,d){
            if ((t/=d/) < ) return c/2*t*t*t*t*t + b;
            return c/2*((t-=2)*t*t*t*t + 2) + b;
        }
    },
    Sine: {
        easeIn: function(t,b,c,d){
            return -c * Math.cos(t/d * (Math.PI/)) + c + b;
        },
        easeOut: function(t,b,c,d){
            return c * Math.sin(t/d * (Math.PI/)) + b;
        },
        easeInOut: function(t,b,c,d){
            return -c/2 * (Math.cos(Math.PI*t/d) - ) + b;
        }
    },
    Expo: {
        easeIn: function(t,b,c,d){
            return (t==) ? b : c * Math.pow(,  * (t/d - 1)) + b;
        },
        easeOut: function(t,b,c,d){
            return (t==d) ? b+c : c * (-Math.pow(, - * t/d) + 1) + b;
        },
        easeInOut: function(t,b,c,d){
            if (t==) return b;
            if (t==d) return b+c;
            if ((t/=d/) < ) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
            return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
        }
    },
    Circ: {
        easeIn: function(t,b,c,d){
            return -c * (Math.sqrt( - (t/=d)*t) - 1) + b;
        },
        easeOut: function(t,b,c,d){
            return c * Math.sqrt( - (t=t/d-1)*t) + b;
        },
        easeInOut: function(t,b,c,d){
            if ((t/=d/) < ) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
            return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
        }
    },
    Elastic: {
        easeIn: function(t,b,c,d,a,p){
            if (t==) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
            if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
            else var s = p/(2*Math.PI) * Math.asin (c/a);
            return -(a*Math.pow(,*(t-=)) * Math.sin( (t*d-s)*(*Math.PI)/p )) + b;
        },
        easeOut: function(t,b,c,d,a,p){
            if (t==) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
            if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
            else var s = p/(2*Math.PI) * Math.asin (c/a);
            return (a*Math.pow(,-*t) * Math.sin( (t*d-s)*(*Math.PI)/p ) + c + b);
        },
        easeInOut: function(t,b,c,d,a,p){
            if (t==) return b;  if ((t/=d/)==) return b+c;  if (!p) p=d*(.*1.5);
            if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
            else var s = p/(2*Math.PI) * Math.asin (c/a);
            if (t < ) return -.*(a*Math.pow(,*(t-=)) * Math.sin( (t*d-s)*(*Math.PI)/p )) + b;
            return a*Math.pow(,-*(t-=)) * Math.sin( (t*d-s)*(*Math.PI)/p )*.5 + c + b;
        }
    },
    Back: {
        easeIn: function(t,b,c,d,s){
            if (s == undefined) s = 1.70158;
            return c*(t/=d)*t*((s+1)*t - s) + b;
        },
        easeOut: function(t,b,c,d,s){
            if (s == undefined) s = 1.70158;
            return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
        },
        easeInOut: function(t,b,c,d,s){
            if (s == undefined) s = 1.70158; 
            if ((t/=d/) < ) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
            return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
        }
    },
    Bounce: {
        easeIn: function(t,b,c,d){
            return c - Tween.Bounce.easeOut(d-t, , c, d) + b;
        },
        easeOut: function(t,b,c,d){
            if ((t/=d) < (1/2.75)) {
                return c*(7.5625*t*t) + b;
            } else if (t < (/2.75)) {
                return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
            } else if (t < (2.5/2.75)) {
                return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
            } else {
                return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
            }
        },
        easeInOut: function(t,b,c,d){
            if (t < d/2) return Tween.Bounce.easeIn(t*2, 0, c, d) * .5 + b;
            else return Tween.Bounce.easeOut(t*-d, , c, d) * . + c*. + b;
        }
    }
}

完整实例下载

本文链接:http://www.cnblogs.com/oooweb/p/javascript-tween-animation.html

原文出处:cloudgamer

《JavaScript 实战》:Tween 算法及缓动效果的更多相关文章

  1. 软件项目技术点(1)——Tween算法及缓动效果

    AxeSlide软件项目梳理   canvas绘图系列知识点整理 Tween算法及缓动效果 软件里在切换步序时需要有过渡动画效果,从当前位置的画面缓动到目标位置的画面.动画效果可重新查看文章系列第一篇 ...

  2. 利用tween.js算法生成缓动效果

    在讲tween类之前,不得不提的是贝塞尔曲线了.首先,贝塞尔曲线是指依据四个位置任意的点坐标绘制出的一条光滑曲线.它在作图工具或动画中中运用得比较多,例如PS中的钢笔工具,firework中的画笔等等 ...

  3. javascript的缓动效果

    这部分对原先的缓动函数进行抽象化,并结合缓动公式进行强化.成品的效果非常惊人逆天.走过路过不要错过. 好了,打诨到此为止.普通的加速减速是难以让人满意的,为了实现弹簧等让人眼花缭乱的效果必须动用缓动公 ...

  4. javascript 45种缓动效果BY司徒正美

    javascript 45种缓动效果 参数 类型 说明 el element 必需,为页面元素 begin number 必需,开始的位置 change number 必需,要移动的距离 durati ...

  5. animation js控制 缓动效果

    <!DOCTYPE html><html><head><meta charset="utf-8" /><title>缓动 ...

  6. 过渡与动画 - 缓动效果&基于贝塞尔曲线的调速函数

    难题 给过渡和动画加上缓动效果是一种常见的手法(比如具有回弹效果的过渡过程)是一种流行的表现手法,可以让界面显得更加生动和真实:在现实世界中,物体A点到B点往往也是不完全匀速的 以纯技术的角度来看,回 ...

  7. [ActionScript 3.0] AS3 用于拖动对象时跟随鼠标的缓动效果

    package com.fylibs.components.effects { import flash.display.DisplayObject; import flash.events.Even ...

  8. Adobe Edge Animate –弹性的方块-使用tweenmax缓动效果

    Adobe Edge Animate –弹性的方块-使用tweenmax缓动效果 版权声明: 本文版权属于 北京联友天下科技发展有限公司. 转载的时候请注明版权和原文地址. 此前有Edge爱好者提出一 ...

  9. quick-cocos2dx 之transition.execute()的缓动效果

    注:本文图片来源(http://hosted.zeh.com.br/tweener/docs/en-us/misc/transitions.html. 侵权请告知,即刻删除) 什么是缓动, 缓动(ea ...

随机推荐

  1. RovingUI组件库-包含堆栈式通知提醒框(Toast)的小程序组件库

    RovingUI是个人在开发小程序过程中将用到的组件集合而成的一个UI库,包含一些基本通用组件(按钮.栅格.通用样式.徽标.通知和面包屑). 源起得归于我在开发中没有找到现成的堆栈式提醒框(比如ant ...

  2. iOS- Swift:如何使用iOS8中的UIAlertController

    1.前言 在前段时间手机QQ:升级iOS8.3后,发图就崩的情况, 就是因为iOS8更新UIAlertController后,仍然使用UIAlertview导致的 具体原因分析 这个可以看腾讯团队发出 ...

  3. 使用docker国内镜像解决方案

    1:蜂巢镜像 https://c.163yun.com/hub#/m/library/ 例如: docker pull hub.c.163.com/library/nginx:1.8 再次执行dock ...

  4. 3dContactPointAnnotationTool开发日志(三二)

      今天就是看怎么把论文的python源码预测出来的smpl模型的姿势和形状参数弄到unity版本的smpl里,但是python版本的和unity版本的不一样.   先看看他的fit_3d.py:   ...

  5. selenium 概念及练习 !

    1.selenium中如何判断元素是否存在? 2.selenium中hidden或者是display = none的元素是否可以定位到? 3.selenium中如何保证操作元素的成功率?也就是说如何保 ...

  6. 爬虫学习之-git拉取远程错误

    本文讲的是把git在最新2.9.2,合并pull两个不同的项目,出现的问题如何去解决 如果合并了两个不同的开始提交的仓库,在新的 git 会发现这两个仓库可能不是同一个,为了防止开发者上传错误,于是就 ...

  7. python接口自动化测试框架实现之操作mysq数据库

    python操作mysql数据库需要使用到mysqlclient库. 安装:pip install mysqlclient python连接mysql数据库分以下步骤: 1.与mysql建立连接: 2 ...

  8. Linux的计划任务

    1. 语法格式:Minute Hour DayOfMonth Month DayOfWeek User Command Minute, 每个小时的第几分钟执行该任务Hour,每天的第几个小时执行该任务 ...

  9. larave5.6 引入自定义函数库时,报错不能重复定义

    方法一:使用function_exists判断 方法二:使用命名空间 namespace test; function test(){ echo 'test/test'; } namespace te ...

  10. java finally 与return

    finally之外的语句块有return,finally语句块没有return:该语句块的返回值被固定下来,等fianlly执行完后返回给调用者 finally语句块与其他语句块同时有return:返 ...