smooth animation - (下)easing 的使用

但是,為什麼感覺動畫那麼不自然呢?

有沒有發現,時間與距離是完全呈現線性變化的,這代表我們假設這個物體在所有的時間點,速度都是相同的。真實生活中通常不會有這樣的事情發生,物體一定都是從靜止狀態逐漸加速,再從移動的狀態中逐漸停止。而上一篇的範例當中,動畫是突然開始,突然停止。在現實生活中,物體的移動速度並非成線性變化,這是造成我們動畫看起來不自然的主要原因。

知道了原理之後,就可以馬上來實作了:

  • 計算距離
  • 重新計算每一次的位移 = 距離 * 比例係數(easing)

把我們原本的 function 改寫成這樣:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function moveScrollY(targetY, speed) {
const scrollY = window.scrollY || window.pageYOffset;
const t = Math.min(0.5, Math.abs((targetY - scrollY) / speed)); // 將時間限制在 0.5(500ms)
let currentTime = 0;
function move() {
currentTime += 1 / 60;
var p = currentTime / t;
var d = Math.cos(Math.PI * pos) - 1); // 利用 cos 函數,重新計算移動的位置。
if (p < 1) {
scrollTo(0, scrollY + (targetY - scrollY) * d);
requestAnimationFrame(move); // 採用 requestAnimationFrame
} else {
scrollTo(0, targetY);
alert('done');
}
}
move();
}

這邊我們加上了一個簡單的 cos 函數,重新計算位移的位置,達到 easing 的效果。詳細 easing 效果,可以到 easing.js 看看,這裡蒐藏了很多 ease 效果。

小結

原本以為篇幅很長,不過基本的動畫原理的確只有這樣而已,加上了 easing 之後,動畫的效果看起來自然很多,當然,你也可以依照自己的經驗調整參數,達到更完美的使用者體驗。

不過,如果可以,盡量不要綁架使用者預設的滾動效果,一來可能會造成效能的問題,二來你綁定的滾動效果如果沒有依照使用者預期反應的話,很容易造成非常差的體驗。

分享到