jQuery 動畫的原理還是很簡單的,靠定時器不斷的改變元素的屬性,我們模擬下 animate 的大致實(shí)現(xiàn),讓元素執(zhí)行一個 2 秒的動畫到坐標(biāo)為 left 50 的區(qū)域。
animate({ left: '50', duration: '2000' }
按照常規(guī)的思路,我們需要 3 個參數(shù):
思路一:等值變化
我們在 animate 內(nèi)部還需要計(jì)算出當(dāng)然元素的初始化布局的位置(比如 500px),那么我們在 2 秒的時間內(nèi)需變換成 50px,也就是運(yùn)行的路勁長就是 500-50 = 450px。
那么算法是不是呼之欲出了?
每毫秒移動的距離: pos = 450/2000 = 0.225px 每毫秒移動: left = 初始位置 (+/-) 每毫秒遞增的距離(pos * 時間)
這樣算法我們放到 setInterval 就會發(fā)現(xiàn)錯的一塌糊涂,我們錯在最本質(zhì)的東西。
JS 是單線程,定時器都是排隊(duì)列的,理論上也達(dá)不到 1ms 繪制一次 dom
所以每次產(chǎn)生的這個下一次繪制的時間差根本不是一個等比的,所以我們按照線性的等值遞增是有誤的。
思路二:動態(tài)計(jì)算
setInterval 的調(diào)用是不規(guī)律的,但是調(diào)用的時間是(2秒)是固定的,我們可以在每次調(diào)用的時候算法時間差的比值,用這個比值去計(jì)算移動的距離就比較準(zhǔn)確了。
remaining = Math.max(0, startTime + duration - currentTime),
通過這個公司我們計(jì)算出,每次 setInterval 調(diào)用的時候,當(dāng)前時間在總時間中的一個位置。
remainin 結(jié)果:
看到?jīng)]有,這個值其實(shí)很符合定時器的特性,也是一個沒有規(guī)律的值,根據(jù)這個值,我們可以得出當(dāng)前位置的一個百分比了:
var remaining = Math.max(0, startTime + options.duration - createTime()) var temp = remaining / options.duration || 0; var percent = 1 - temp;
pecent結(jié)果
那么這個移動的距離就很簡單了,我把整個公式就直接列出來了。
function tick(){ //每次變化的時間 var remaining = Math.max(0, startTime + duration - createTime()) var temp = remaining / duration || 0; var percent = 1 - temp; //最終每次移動的left距離 var leftPos = (endLeft- startLeft) * percent +startLeft; }
leftPos 就是每次移動的距離了,基本上比較準(zhǔn)確了,事實(shí)上 jQuery 內(nèi)部也就是這么干的,這里 13 代表了動畫每秒運(yùn)行幀數(shù),默認(rèn)是13毫秒,屬性值越小,在速度較快的瀏覽器中(例如,Chrome),動畫執(zhí)行的越流暢,但是會影響程序的性能并且占用更多的 CPU 資源,在新的游覽器中,我們都可以采用 requestAnimationFrame 會更優(yōu)。
請驗(yàn)證,完成請求
由于請求次數(shù)過多,請先驗(yàn)證,完成再次請求
打開微信掃碼自動綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報(bào)