这一篇是接着上一篇 翻译。原文点击。
上一篇主要讲了animate的基本原理。这一篇主要将几种常见的delta。
进度函数delta
动画是随着时间变化而变化的,在javascript动画中,这个变化的原则是由delta来决定的。
不同的delta使动画的变化速度,加速度和其他的一些参数完全不同。
数学公式经常会被用到。对于一些已经离开学校多年的web从业者可能对于这些公式比较陌生。但是,在这里我将应用一些非常流行的函数,来看看他们怎么工作。
下面这里的动画例子依次提供不同的delta。
线性 delta
function linear(progress){
return progress;
}
Paste_Image.png
水平线是progress(时间的进度),垂直线是
delta(progress)
也就是动画移动的进度。我们已经看出来,线性的delta使动画匀速进行。
<div onclick="move(this.children[0], linear)" class=''example_path">
<div class="exmple_block"></div>
</div>
n次幂函数
delta函数是progress的n次幂,比较特殊的情况,比如 n = 2
或n = 3
。
例如:
function quad(progress){
return Math.pow(progress, 2);
}
Paste_Image.png
Circ: a piece of circle
例如
function circ(progress){
return 1 - Math.sin(Math.acos(progess))
}
Paste_Image.png
Back: the bow function
这个函数像一个弓:首先我们先拉弓,然后发射。
function back(progress, x) {
return Math.pow(progress, 2) * ((x + 1) * progress - x)
}
Paste_Image.png
Bounce
想象一下,我们放开一个球自由落体,然后反弹几次最后停止。
这个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)
}
}
}
还有其他的bounce函数。
Elastic
这个函数依靠x这个额外的参数,这个参数定义了初始的范围。
function elastic(progress, x) {
return Math.pow(2, 10 * (progress-1)) * Math.cos(20*Math.PI*x/3*progress)
}
Paste_Image.png
反函数(easeIn, easeOut, easeInOut)
一个javascript框架通常提供一系列的delta,这正向的使用叫做easeIn
有的时候,我们要求这个动画和时间的进度相反的,这个叫做easeOut
并且应用通过"time-reversing"delta。
easeOut
deltaEaseOut = 1 - delta(1 - progress)
例如:
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);
}
}
}
function makeEaseOut(delta) {
return function(progress) {
return 1 - delta(1 - progress)
}
}
var bounceEaseOut = makeEaseOut(bounce)
Paste_Image.png
easeInOut
另一个选项是delta影响开始的时候和结束的时候,叫做 easeInOut
if (progress <= 0.5) { // the first half of the animation)
return delta(2 * progress) / 2
} else { // the second half
return (2 - delta(2 * (1 - progress))) / 2
}
function makeEaseInOut(delta) {
return function(progress) {
if (progress < .5)
return delta(2*progress) / 2
else
return (2 - delta(2*(1-progress))) / 2
}
}
bounceEaseInOut = makeEaseInOut(bounce)
Paste_Image.png
step执行函数
几乎所有的东西,你都可以animate,除了移动,还有change opaciy, width, height, color...等等其他任何你可以想想的。
例如改变背景色:
function highlight(elem) {
var from = [255,0,0], to = [255,255,255]
animate({
delay: 10,
duration: 1000,
delta: linear,
step: function(delta) {
elem.style.backgroundColor = 'rgb(' +
Math.max(Math.min(parseInt((delta * (to[0]-from[0])) + from[0], 10), 255), 0) + ',' +
Math.max(Math.min(parseInt((delta * (to[1]-from[1])) + from[1], 10), 255), 0) + ',' +
Math.max(Math.min(parseInt((delta * (to[2]-from[2])) + from[2], 10), 255), 0) + ')'
}
})
}
例如利用bounce模仿text type:
function animateText(textArea) {
var text = textArea.value
var to = text.length, from = 0
animate({
delay: 20,
duration: 5000,
delta: bounce,
step: function(delta) {
var result = (to-from) * delta + from
textArea.value = text.substr(0, Math.ceil(result))
}
})
}
例如模仿足球掉落:
var img = document.getElementById('ball')
var field = document.getElementById('field')
img.onclick = function() {
var from = 0
var to = field.clientHeight - img.clientHeight
animate({
delay: 20,
duration: 1000,
delta: makeEaseOut(bounce),
step: function(delta) {
img.style.top = to*delta + 'px'
}
})
}
例如模仿足球向左向下掉落:
img.onclick = function() {
var height = document.getElementById('field').clientHeight - img.clientHeight
var width = 100
animate({
delay: 20,
duration: 1000,
delta: makeEaseOut(bounce),
step: function(delta) {
img.style.top = height*delta + 'px'
}
})
animate({
delay: 20,
duration: 1000,
delta: makeEaseOut(quad),
step: function(delta) {
img.style.left = width*delta + "px"
}
})
}
css 变化(transitions)
现在大部分现代的浏览器支持css transition, 一种通过css来实现的动画。
这种动画很简单,设置css transition-duration属性和transition-property属性。
例如:
.animated {
transition-property: background-color;
transition-duration: 2s;
}
具体例子:
<style>
.animated {
transition: background-color 2s;
-webkit-transition: background-color 2s;
-o-transition: background-color 2s;
-moz-transition: 2s;
}
</style>
<div class="animated" onclick="this.style.backgroundColor='red'">
<span style="font-size:150%">Click to animate (no IE, no FF<4)</span>
</div>
因为css transition还是一个草案,所以需要加上前缀。
通常没有浏览器支持没有前缀的tansition属性。
css transition的一些限制:
- css transition 可以设置 delta, 但是只有有限的种类。
- 只有css的属性可以操纵,但是好处是多个属性可以一起改变。
优化的一些建议
- 多个timer导致cpu过载。解决方案一次redraw(也就是一个timer中)完成多个 step 动作。
- 由于元素在document中的位置越深,计算量越大。解决方案如下:
- 把该元素提取出来,加到body中,然后position:absolute。
- 操作它
- 插回去
总结
动画都是通过setInterval来完成的。通常delay在10ms ~ 50ms,在每一个delay中,更新元素的某些属性。
其实这个不局限在元素上,也可以是别的东西。
通常的animate框架接受的参数:
1.delay - 帧之间的间隔
2.duration - 动画的时间
3.delta - 时间进度和动画进度的对应关系
4.step - 真正的动画操作
请记住:如果你感觉动画卡顿,把多个动画和到一个timer中,或者把元素提取到body 上作为绝对元素来操作。
网友评论