Javascript动画的兑现原理剖判

2019-07-23 02:28栏目:WRB前端

假诺有那样一个动画效果供给:把贰个div的上涨的幅度从100px变化到200px。写出来的代码可能是那般的:

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刷新一遍),把间隔跟刷新率同步效果越来越好。

假存在那样三个卡通效果供给:把三个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(即每秒刷新74遍,也便是每隔约13ms刷新叁遍),把间隔跟刷新率同步效果越来越好。

你恐怕感兴趣的篇章:

  • javascript 流畅动画达成原理

版权声明:本文由威尼斯人app发布于WRB前端,转载请注明出处:Javascript动画的兑现原理剖判