【翻译】javascript 动画道理浅析

动画

原文:http://javascript.info/tutori…

一般,框架会为你处置惩罚动画。然则,你能够想晓得仅仅用javascript怎样来完成动画,和能够涌现的一些问题。明白这项手艺关于建立庞杂的动画是很有协助的,纵然在框架的协助下。

动画基本

javascript的动画是经由历程周期性的转变DOM元素的style 或许 canvas 的对象。
全部的动画历程被分成了很小的步骤(step),每个步骤被定时器挪用。由于定时器的周期异常短,所以动画看起来是一连的。
伪代码:

var id = setInterval(function(){
    /*当前显现帧*/
    if(/*完成*/) clearInterval(id)
}, 10)

上面代码每一帧的间隔是 10ms ,意味着每秒钟有100帧。
在大多数的javascript框架中 10-15ms的delay是默许的。越短的延时让动画看起来越发流通,然则只要在阅读器足够快的时刻,每一步的动画才会准时运转。
假如动画须要许多盘算,CPU能够会100%的负载,动画就会变得迟缓。这类情况下,delay就应当被增添。比方,delay 40ms 就是每秒25帧,靠近24帧的影戏规范。

setInterval 而不是用 setTimout(其实在当代阅读器中大多运用requestAnimationFrame)

我们运用setInterval,而不是递归的运用setTimeout,是由于我们想要一帧一个delay,而不是一切帧之间有一个牢固的delay.查阅Understanding timers: setTimeout and setInterval来相识setInterval和递归的setTimeout之间到底有什么差别。(译者:经测试最新的chrome > 56中,setInterval的行动跟本文中形貌的差别。当函数实行时候凌驾了delay时候,下一个函数不会立时运转,依然会等一个delay的间隔,再实行。但本文仍有参考价值)

例子

比方,一个元素挪动经由历程转变element.stye.left从0到100px。每10ms转变1px。

<html>
<head>
<link type="text/css" rel="stylesheet" href="/files/tutorial/browser/animatio/animate.css">
<script>
    function move(elem) {
        var left = 0;
        function frame(){
            left++ // 更新参数
            elem.style.left = left + 'px' // 显现帧
            if(left === 100) //搜检完毕前提
            clearInterval(id)
        }
        var id = setInterval(frame, 10) //没10ms绘制一次
    }
</script>
</head>
<body>
<div onclick="move(this.children[0])" class="example_path">
<div class="example_block"></div>
</div>
</body>
</html>

在新的窗口翻开

动画重构

为了让动画越发通用,我们引见下面的一些参数:

  • delay
      每一帧之间的间隔(ms).比方,10ms

  • duration
      全部动画完成须要的时候(ms)。比方:1000ms

当动画最先的时刻,我们也能够用:

  • start   动画最先的时候,start = new Date
    动画历程的中心,每一帧我们须要盘算:

  • timePassed
      从动画最先所经由的时候(ms)。

  从0到动画(duration)完毕.然则偶然能够会凌驾完毕时候,由于阅读器的计时器并不正确。

  • progress
    已由去的动画时候作为份子,盘算每一帧经由历程公式timePassed/duration。值得局限一般是0到1。

比方,progress的值为0.5就是说动画时候(duration)已由去了一半。

  • delta(progress)
    一个返回当前动画进度的函数。

比方,我们让高度属性从0%变化到100%。
我们能够让动画匀称的显现,如许动画进度看起来就是线性的。
Mapping:
->progress = 0 -> height = 0%
->progress = 0.2 -> height = 20%
->progress = 0.5->height = 50%
->progress = 0.8 -> height = 80%
->progress = 1 -> height = 100%
《【翻译】javascript 动画道理浅析》

然则我们能够想让动画迟缓的最先然后再加快。如许的话经由一半的动画时候高度能够只要25%
,然后逐步加快到100%。
Mapping:
->progress = 0 -> height = 0%
->progress = 0.2 -> height = 4%
->progress = 0.5->height = 25%
->progress = 0.8 -> height = 64%
->progress = 1 -> height = 100%
《【翻译】javascript 动画道理浅析》

  • delta(progress) 是一个映照动画进度增量的函数,
    动画进度一般是0到1之间的一个数字。

这篇文章会用一些例子进一步议论几种增量函数

  • step(delta)
    这个函数是实际上用来做这件事的函数。

它盘算出增量的效果而且应用它。
关于这个高度的例子,他们多是:

function state(delta) {
    elem.style.height = 100*delta + "%"
}

到现在为止几个主要的参数是:
-> delay是setInterval的第二个参数。
-> duration是动画完成须要的时候。
-> progress是动画已经由的时候,除以duration使它的值在0到1之间。
-> delta经由历程当前的时候,盘算当前的动画进度。
-> step做了视觉上(?)的事变。它取得当前的动画进度,而且把它应用在元素上。

通用的动画

让我们把上面议论的简朴的写成一个可扩大的动画中心。
下面的动画函数实行时候管理而且把事变分配给delta和step:

function animate(opts) {
    var start = new Date;
    var id = setInterval(function(){
        var timePassed = new Date - start;
        var progress = timePassed / opts.duration;
        if(progress > 1) progress = 1;
        var delta = opts.delta(progress)
        opts.step(delta)
        if(progress == 1) {
            clearInterval(id)
        }
    }, opts.delay || 10)
}

参数对象应当包括以下的一些动画属性:
-> delay
-> duration
-> function delta
-> function step
这个算法完整遵照上面的形貌

Example

让我们基于这个来建立一个挪动的动画

function move(element, delta, duration){
    var to = 500;
    animate({
        delay: 10,
        duration: duration || 1000,
        delta: delta,
        step: function(delta){
            element.style.left = to * delta + 'px'
        }
    })
}

它把事变指派给animate,给animate传入了delay,用户供应的duration, delta, 和 step
delta = function(p) { return p}
  意味着动画历程一向是匀称的
step
  用一个简朴的公式映照0..1,delta返回一个进度值 0..to。把这些效果应用到element.style.left。
用法:

<div onclick="move(this.children[0], function(p) {return p})" 

class="example_path">
    <div class="example_block"></div>
</div>

数学,进度增量函数

动画就是是依据给定的划定规矩,一向转变属性。在javascript动画中,这个划定规矩就是delta函数来完成的。
差别的delta使动画的速率,加快度和其他的参数表现出林林总总的情势。
数学公式一般被用在这里。然则它们关于只做web编程和遗忘学校里的数学的人来讲,能够很生疏。在这个章节,我们将阅读许多的受欢迎的公式并看一下它们是怎样事变的。
动画活动的例子,供应差别的delta.

线性 delta

function linear(progress){
    return progress;
}

《【翻译】javascript 动画道理浅析》

程度方向指的是时候进度,垂直方向指的是动画历程。
我们已能看见了。线性的delta使动画以牢固的速率举行。
Power of n
也是一个简朴的例子。delta是progress的n次方。比方2次,3次方等。
比方2次方

function quad(progress) {
    return Math.pow(progress, 2)
}

《【翻译】javascript 动画道理浅析》

增添加快度的影响。比方,下面这个图片是5次方。

《【翻译】javascript 动画道理浅析》

Circ: 圆的一部分

function circ(progress) {
    return 1 - Math.sin(Math.acos(progress))
}

《【翻译】javascript 动画道理浅析》

Back: the bow function
这个函数向弓一样事变:起首我们”拉完工,然后发射出去”。
不像先前的函数,它会依赖于一个附加的参数x,这就是“弹性系数”。
它定义了“拉弓”的间隔。
代码是:

function back(progress, x) {
    return Math.pow(progress, 2) * ((x + 1) * progress - x)
}

图象x=1.5
《【翻译】javascript 动画道理浅析》

bounce(弹跳)
设想一下我们开释一个球,它掉在地上,然后弹跳频频,末了住手。
bounce事实上做了相反的事变。属性将会一向转变晓得它到达目标点。
这个函数比之前要庞杂一些,也没有简朴的数学公式。

function bounce(progress) {
    for(var a = 0, b=1, result; 1; a+=b, b /= 2) {
        if (progress >= (7-4*a) / 11){
            return -Math.pow(11 - 6 * a - 11 * progress) / 4, 2) + Math.pow(b, 2)
        }
    }
}

*这段代码曲子 MooTools.FX.Transitions.据我所知,依然有其他完成bounce的算法。
Elastic 弹性
这个函数也依赖于分外的参数x,x定义了初始局限。

function elastic(progress, x){
    return Math.pow(2, 10 * (progress - 1)) * Math.cos(20 * Math.PI * x/3 *progress)
}

图象 x=1.5
《【翻译】javascript 动画道理浅析》

在这个例子中,为了让动画越发腻滑,时候是2s.
反向函数(Reverse functions)
一个javascript框架经常会供应的一种delta函数。
它们的直接运用被称作 easeIn.
偶然的时刻,须要以时候倒退的体式格局来展现动画。这就叫做easeout 被’time-reversing’delta来完成。
未完待续
第一次翻译点东西,质量不好,主如果做记任命。内里有许多比较’术语’的,不好翻,最悦目原文。背面我也会继承修正。

    原文作者:liangpure
    原文地址: https://segmentfault.com/a/1190000008570887
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞