這篇文章主要介紹了Javascript動畫的實現原理淺析,本文用兩個實例來解釋Javascript動畫的實現原理,需要的朋友可以參考下
假設有這樣一個動畫功能需求:把一個div的寬度從100px變化到200px。寫出來的代碼可能是這樣的:
代碼如下:
animate1(document.getElementById('test1'), 200, 1000);
有沒有更好的做法呢?下面先來看一道小學數學題:
代碼如下:
這道題帶來的啟發是,某個時刻的路程是可以通過特定公式計算出來的。同理,動畫過程中某個時刻的值也可以通過公式計算出來,而不是累加得出:
代碼如下:
var timerId = setInterval(function() {
var percentage = (new Date - startTime) / duration;
var stepValue = startValue + (endValue - startValue) * percentage;
element.style.width = stepValue + 'px';
if (percentage >= 1) {
clearInterval(timerId);
element.innerHTML = new Date - startTime;
}
}, 13);
}
animate2(document.getElementById('test2'), 200, 1000);
這樣改良之後,可以看到動畫執行耗時最多只會有10幾ms的誤差。但是問題還沒完全解決,在浏覽器開發工具中檢查test2元素可以發現,test2的最終寬度可能不止200px。仔細檢查animate2函數的代碼可以發現:
1.percentage的值可能大於1,可以通過Math.min限制最大值解決。
2.即使保證了percentage的值不大於1,只要endValue或startValue為小數,(endValue - startValue) * percentage的值也可能產生誤差,因為Javascript小數運算的精度不夠。其實我們要保證的只是最終值的准確性,所以在percentage為1的時候,直接使用endValue即可。
於是,animate2函數的代碼修改為:
代碼如下:
var timerId = setInterval(function() {
// 保證百分率不大於1
var percentage = Math.min(1, (new Date - startTime) / duration);
var stepValue;
if (percentage >= 1) {
// 保證最終值的准確性
stepValue = endValue;
} else {
stepValue = startValue + (endValue - startValue) * percentage;
}
element.style.width = stepValue + 'px';
if (percentage >= 1) {
clearInterval(timerId);
element.innerHTML = new Date - startTime;
}
}, 13);
}
還有最後一個疑問:setInterval的間隔為何設為13ms?原因是當下顯示器的刷新率一般不超過75Hz(即每秒刷新75次,也就是每隔約13ms刷新一次),把間隔跟刷新率同步效果更好。