1

I have created a script that animates the height of an element in 500ms.

The timer works fine but I am struggling to make the height increase consistently.

How do I animate the height smoothly within the time period? It jumps at the moment.

I want to replace the following with something smarter:

self.startHeight + 5

I imagine it has something to do with the speed and elapsed time?

https://jsfiddle.net/zrm7xena/1/

(function () {
    'use strict';

    var animator = {};

    animator.endHeight = 200; //The end height
    animator.interval = null; //Create a variable to hold our interval
    animator.speed = 500; //500ms
    animator.startHeight = 0; //The start height

    animator.animate = function (el) {
        var self = this,
            startTime = Date.now(); //Get the start time

        this.interval = setInterval(function () {
            var elapsed = Date.now() - startTime, //Work out the elapsed time
                maxHeight = self.maxHeight; //Cache the max height 

            //If the elapsed time is less than the speed (500ms)
            if (elapsed < self.speed) {
                console.log('Still in the timeframe');

                //If the client height is less than the max height (200px)
                if (el.clientHeight < self.endHeight) {
                    self.startHeight = self.startHeight + 5; //Adjust the height
                    el.style.height = self.startHeight + 'px'; //Animate the height
                }
            } else {
                console.log('Stop and clear the interval');
                el.style.height = self.endHeight + 'px';
                clearInterval(self.interval);
            }
        }, 16); //60FPS
    };

    animator.animate(document.getElementById('box'));
}());

Thanks in advance!

Carorus gave a great answer below. I have updated my jsfiddle so you can see the final code working:

https://jsfiddle.net/zrm7xena/8/

Typhoon posted a great link in relation to the browser FPS:

How to determine the best "framerate" (setInterval delay) to use in a JavaScript animation loop?

I would probably use request animation frame instead of a setInterval:

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

Cheers all!

1 Answer 1

2

The harcoded 5 that you are using for the height increment doesn't allow the animation to complete the entire final height (200) in the time that you are setting (500ms), you need to calculate the height increment based on the final height, the animation time and the interval to make it consistent:

(function () {
'use strict';

var animator = {};

animator.endHeight = 200; //The end height
animator.interval = null; //Create a variable to hold our interval
animator.speed = 500; //500ms
animator.startHeight = 0; //The start height
animator.interval = 16;

animator.animate = function (el) {
    var self = this,
    startTime = Date.now(); //Get the start time
    //calculating height variation
    self.deltaHeight = (animator.endHeight / animator.speed) * animator.interval;
    this.intervalId = setInterval(function () {
        var elapsed = Date.now() - startTime, //Work out the elapsed time
            maxHeight = self.maxHeight; //Cache the max height 

        //If the elapsed time is less than the speed (500ms)
        if (elapsed < self.speed) {
            console.log('Still in the timeframe');

            //If the client height is less than the max height (200px)
            if (el.clientHeight < self.endHeight) {
                self.startHeight = self.startHeight + self.deltaHeight; //Adjust the height
                el.style.height = self.startHeight + 'px'; //Animate the height
            }
        } else {
            console.log('Stop and clear the interval');
            el.style.height = self.endHeight + 'px';
            clearInterval(self.intervalId);
        }
    },  animator.interval); //60FPS
};

animator.animate(document.getElementById('box'));
}());
4
  • That works brilliantly. Thanks a lot Carorus! I knew the increase of 5 never reached 200 in 500ms but I was unable to figure out how to do it right. I thought it had something to do with the speed but kept hitting a wall. Amazing answer. You have helped me understand how to approach things like this going forward!
    – Paddy
    Commented Apr 21, 2016 at 22:10
  • Also, just a note, I don't think '16' is consistent across all browsers in determining 60fps, which can directly affect your animation across browsers. stackoverflow.com/questions/2940054/… Commented Apr 21, 2016 at 22:13
  • Yeah 16 is basically 1000 / 60. I will keep that in mind Typhoon. Thanks for the additional answer link.
    – Paddy
    Commented Apr 21, 2016 at 22:16
  • @Carorus just out of curiosity. How would you handle a consistent movement using a different endHeight? For example: a slider with different left positions: (left / speed) * fps. That calculation would not work if the left value kept changing (it would create different speeds).
    – Paddy
    Commented Apr 21, 2016 at 23:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.