Search code examples
javascriptjqueryjquery-animateeasing

jQuery animate() - get progress with easing


Currently, I'm using this code to animate a bar-graph-esque element:

$('.anim').animate({
    right: `${100-(e/max*100)}%`,
    backgroundColor: colors[0]
},{
    duration: 1500,
    easing: 'easeInQuart',
    progress: function(animation, progress, msRemaining) {
        console.log(100 * progress + "%");
        document.getElementById('progress').innerText = Math.round(e * progress);
    }
});

(jsfiddle)

Where e is the value of the bar and max is the total bar graph scale.

The element progress is supposed to show the value of the bar graph as it increases.

However, since I'm using 'easeInQuart', the numeric progress of the bar graph isn't actually its visual state.

Here's a slowed down example where you can clearly see that the progress text counts up at a constant rate, but the animated bar fills in with easing.

Is there a way to get the progress, factoring in the exponential growth of 'easeInQuart'?

Also: I might change the easing style, so I'd like the solution to be adaptable.


Solution

  • To obtain an "eased" value, instead of a progress callback, use a step callback and inspect its now argument.

    In this case, as none of the animated properties gives you the value you want, you can animate a custom property, which jQuery makes very simple.

    var e = 3210;
    var max = 4504;
    var colors = ['#28ad8a'];
    $('.anim').css({
      'val': 0 // custom property: start value 
    }).animate({
      'right': `${100-(e/max*100)}%`,
      'val': e, // custom property: final value: 
      'backgroundColor': colors[0]
    }, {
      'duration': 1500,
      'easing': 'easeInQuart',
      'step': function(now, tween, msRemaining) {
        if (tween.prop === 'val') { // this callback is called once per property per step, therefore filter out all but the property of interest, 'val'
            $('#progress').text(Math.round(now));
        }
      }
    });
    

    fiddle