国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > JavaScript > 正文

Javascript動畫的實現原理淺析

2024-05-06 16:15:37
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了Javascript動畫的實現原理淺析,本文用兩個實例來解釋Javascript動畫的實現原理,需要的朋友可以參考下
 

假設有這樣一個動畫功能需求:把一個div的寬度從100px變化到200px。寫出來的代碼可能是這樣的:

復制代碼代碼如下:

<div id="test1" style="width: 100px; height: 100px; background: blue; color: white;"></div>
function animate1(element, endValue, duration) {
    var startTime = new Date(),
        startValue = parseInt(element.style.width),
        step = 1;
    
    var timerId = setInterval(function() {
        var nextValue = parseInt(element.style.width) + step;
        element.style.width = nextValue + 'px';
        if (nextValue >= endValue) {
            clearInterval(timerId);
            // 顯示動畫耗時
            element.innerHTML = new Date - startTime;
        }
    }, duration / (endValue - startValue) * step);
}

 

animate1(document.getElementById('test1'), 200, 1000);


原理是每隔一定時間增加1px,一直到200px為止。然而,動畫結束后顯示的耗時卻不止1s(一般是1.5s左右)。究其原因,是因為setInterval并不能嚴格保證執行間隔。

 

有沒有更好的做法呢?下面先來看一道小學數學題:

復制代碼代碼如下:

A樓和B樓相距100米,一個人勻速從A樓走到B樓,走了5分鐘到達目的地,問第3分鐘時他距離A樓多遠?

勻速運動中計算某個時刻路程的計算公式為:路程 * 當前時間 / 時間 。所以答案應為 100 * 3 / 5 = 60 。

 

這道題帶來的啟發是,某個時刻的路程是可以通過特定公式計算出來的。同理,動畫過程中某個時刻的值也可以通過公式計算出來,而不是累加得出:

 

復制代碼代碼如下:

<div id="test2" style="width: 100px; height: 100px; background: red; color: white;"></div>
function animate2(element, endValue, duration) {
    var startTime = new Date(),
        startValue = parseInt(element.style.width);

 

    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函數的代碼修改為:

復制代碼代碼如下:

function animate2(element, endValue, duration) {
    var startTime = new Date(),
        startValue = parseInt(element.style.width);

 

    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刷新一次),把間隔跟刷新率同步效果更好。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 济源市| 鄄城县| 察雅县| 萝北县| 华安县| 招远市| 庆安县| 安吉县| 山阴县| 雅安市| 莱阳市| 龙里县| 乡宁县| 内江市| 杭锦后旗| 南皮县| 鹿邑县| 安康市| 大埔区| 莱西市| 上高县| 曲阜市| 筠连县| 玉林市| 宜宾县| 友谊县| 兴文县| 辽中县| 托克逊县| 绥德县| 濉溪县| 五常市| 黎平县| 三明市| 贵阳市| 个旧市| 潜江市| 中方县| 潼南县| 吉隆县| 台州市|