0

我尝试用setIntervaljavascript 来实现动画效果,我想要一个div的宽度增加200px(盒子的原点宽度是100px1000ms

var MAX = 300, duration = 1000;
var inc = parseFloat( MAX / duration );

var div = $('div')[0];
var width = parseInt(div.style.width, 10);

function animate (id) {
    width += inc;
    if (width >= MAX) {
        clearInterval(id);
        console.timeEnd("animate");
    }
    div.style.width = width + "px";
}

console.time("animate");
var timer = setInterval(function () {
    animate(timer);
}, 0)

我用console.time来计算需要多少时间,但是,它总是需要 3 秒或更多,而不是 1 秒。

那么我的代码有什么问题?

演示在这里

但是当我使用 jquery animate 时,它​​就像我指出的那样:

console.time("animate");
$('div').animate({
    width: '300px'
}, { 
    duration: 1000,
    complete: function () {
        console.timeEnd("animate");
    }
})

这是演示

那么为什么jquery可以实现呢?秘诀是什么?

4

2 回答 2

1

“秘密”是计算每帧需要采取的步骤。

这是一个更新的示例(进行了一些优化):http:
//jsfiddle.net/AbdiasSoftware/nVgTj/7/

//init some values
var div = $('div')[0].style;
var height = parseInt(div.height, 10);
var seconds = 1;

//calc distance we need to move per frame over a time
var max = 300;
var steps = (max- height) / seconds / 16.7;

//16.7ms is approx one frame (1000/60)

//loop
function animate (id) {
    height += steps; //use calculated steps
    div.height = height + "px";

    if (height < max) {
        requestAnimationFrame(animate);
    }
}

animate();

请注意,正如 hh54188 指出的那样,requestAnimationFrame并非在所有浏览器中都可用(Chrome 和 Firefox 使用前缀支持它)。

您可以使用这个 polyfill,它允许您使用调用,但setTimeout如果requestAnimationFrame不可用,则优雅地回退到。

http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

于 2013-06-17T09:20:11.457 回答
0

@Ken 说的解决方案是可用的,但是浏览器不支持requestAnimationFrame,它无法工作;

我在代码中犯的错误是,我计算的增量每 1ms 增加,但计时器每 4ms 执行我的动画函数(根据最小延迟)。

所以为了保险起见,我们最好手动设置定时器延迟,比如13ms(jquery动画中的间隔),增加的应该是:

var inc = parseFloat( MAX / duration ) * 13;

使用13 * perOneMillisecond作为增量匹配13ms区间

这是Demo,然后您几乎可以像 jquery 一样检查时间成本(但仍然慢一些,为什么?)

于 2013-06-20T06:05:20.420 回答