Smooth div width change in javascript

12,729

Solution 1

One of the biggest causes of 'juddery' animations for me has always been frame rate. If your frame rate is too slow, obviously the animation 'judders'. But if it is too fast for the browser to handle, the browser gets confused, and you get a different kind of 'juddery'.

I'd recommend a frame rate of between 13 and 30 milliseconds. JQuery is supposed to use 13ms, but I've found that that is sometimes still too fast. I generally start with 16ms, and experiment from there.

The key is to ensure that you time it so that one frame starts as or after the previous frame is finished. This will depend on the code you process. I notice that you call the next frame before you begin processing the current frame, so it may be possible that you're still getting backed up. Perhaps try:

function Update(){
    test();
    requestAnimFrame( Update ); 
}

Your fallback function has a frame rate of 200 / 100, which is 2ms. It is extremely unlikely that your browser can complete the animation in 2ms, so it is likelyto get backed up. requestAnimationFrame uses a maximum frame rate of 16ms.

UPDATE:

The problem you're having, according to your jsfiddle, is that, while you're calculating your percentage often, the changes to the percentage are very small, and they don't translate into a change in the width of the div. This http://jsfiddle.net/RmXr9/13/ should demontrate the changes in the percentage, and show the corrsponding changes in actual width. So, although you do a calculation often (maybe 60 times a second), the actual visual change only happens once every 16 frames or so. So, your actual frame rate is only about 4 frames per second, which makes a 'juddery' animation. Your only options, I'm afraid, are to make the animation run faster (perhaps by decreasing your length variable), or to make the div much longer (or both).

As an aside, I notice you don't have a way to stop the animation at the end, and I've added that into the jsfiddle as well.

Solution 2

try using css transitions. You get way smoother animations, but requires you to structure your code a bit differently. An example of a css transition property is this:

transition:300ms linear;

then whatever property you change (the width for example) will make a smooth linear 300 millisecond transition towards it.

so making a smooth width change is as simple as setting up the transition then doing something like this in javascript:

div.style.width="400px";

Here's a quick example i mocked up:

http://jsfiddle.net/nTMsC/1/

here's a nice tutorial to get you started: http://www.css3.info/preview/css3-transitions/

Share:
12,729
Sir
Author by

Sir

Hello :)

Updated on June 04, 2022

Comments

  • Sir
    Sir almost 2 years

    I have a simple function which is increasing the width of a div but its not doing it smoothly its kinda of "juddery".

    I'm using request animation frame to do this on Chrome.. and I decided not to round the numbers so I could get decimal width increments.. but I can't get it to be smooth at all was wondering how I can improve on my method.

    This is my function:

    function test(data){
    
    
    var start = parseInt(data.start);
    var length = parseInt(data.length); //total length in minutes to complete
    var dif = (new Date().getTime() / 1000) - start; //start holds seconds since epoch
    var minutes = dif / 60; //convert seconds past into minutes past
    var percentage = (minutes/length) * 100;
    
    if(percentage > 100){ percentage = 100; }
    
        if( percentage != 100 ){
            document.getElementById('r').style.width = percentage+'%';
            document.getElementById('rt').innerHTML = Math.round(percentage)+'%';
        } else if (percentage == 100 ){
            document.getElementById('r').style.width = percentage+'%';
            document.getElementById('rt').innerHTML = 'COMPLETED';
        }
    }
    

    My function is called like this:

    window.requestAnimFrame = (function(){
      return  window.requestAnimationFrame       || 
              window.webkitRequestAnimationFrame || 
              window.mozRequestAnimationFrame    || 
              window.oRequestAnimationFrame      || 
              window.msRequestAnimationFrame     || 
              function( callback,  element){
                window.setTimeout(callback, 200 / 100);
              };
    })();
    
    function Update(){
        requestAnimFrame( Update ); 
        test();
    }
    

    JSFIddle: http://jsfiddle.net/RmXr9/7/

    Any suggestions on ways to improve the smoothness of div width incrementing ?