Reputation: 15626
I try to use setInterval
to achieve animate effect in javascript, I want a div
's width increase 200px
(the box's origin width is 100px
) in 1000ms
:
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)
and I use the console.time
to calculate how much time it take, however, it always take 3 second and more, not 1 second.
So what's wrong with my code?
the Demo is here
but when I use jquery animate, it just as the same time as I pointed:
console.time("animate");
$('div').animate({
width: '300px'
}, {
duration: 1000,
complete: function () {
console.timeEnd("animate");
}
})
Here is the Demo
So why jquery could achieve it?What's the secret?
Upvotes: 0
Views: 545
Reputation:
The "secret" is to calculate the steps you need to take per frame.
Here is an updated example (with some optimizations):
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();
Note that as hh54188 points out, requestAnimationFrame
is not available in all browsers yet (Chrome and Firefox supports it with prefixes).
You can use this polyfill which allow you to use the call no matter, but fall backs gracefully to setTimeout
if requestAnimationFrame
shouldn't be available.
http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
Upvotes: 1
Reputation: 15626
The solution @Ken said is an available one, but the browser don't support requestAnimationFrame
, it could't work;
The mistake I made in my code is, what I calculate the increasement is increased per 1ms, but the timer execute my animate function per 4ms (according to the minimum delay).
So for some insurance,we better set the timer delay by hand, like 13ms
(the interval in jquery animation), and the increasement should be:
var inc = parseFloat( MAX / duration ) * 13;
use the 13 * perOneMillisecond
as the increasement for matching the 13ms
interval
Here is the Demo, then you can check time cost almost as the jquery(but still slower some, why?)
Upvotes: 0