這一篇是接著上一篇 翻譯。原文點擊。
上一篇主要講了animate的基本原理。這一篇主要將幾種常見的delta。
進度函數delta
動畫是隨著時間變化而變化的,在javascript動畫中,這個變化的原則是由delta來決定的。
不同的delta使動畫的變化速度,加速度和其他的一些參數完全不同。
數學公式經常會被用到。對于一些已經離開學校多年的web從業者可能對于這些公式比較陌生。但是,在這里我將應用一些非常流行的函數,來看看他們怎么工作。
下面這里的動畫例子依次提供不同的delta。
線性 delta
function linear(progress){
return progress;
}
水平線是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);
}
Circ: a piece of circle
例如
function circ(progress){
return 1 - Math.sin(Math.acos(progess))
}
Back: the bow function
這個函數像一個弓:首先我們先拉弓,然后發射。
function back(progress, x) {
return Math.pow(progress, 2) * ((x + 1) * progress - x)
}
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)
}
反函數(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)
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)
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 上作為絕對元素來操作。