Last Updated: February 25, 2016
·
1.367K
· amoniker

Animate the Inanimate

jQuery's animate() function is great for performing custom animations, but it sadly does not work with all CSS properties.

When you'd like to animate a property that isn't handled by default, there's a simple trick you can use.

For example, let's say I have a 3D element which I want to rotate by animating, but I find that the transform property doesn't respond when passed to animate().

By using an arbitrary CSS property which accepts an integer value, we can access the current state of this value in the step() function of the animation in order to update the rotation.

You can use any integer-based CSS property, but in this case we'll employ the little-used orphans property to pass as the step value. We'll animate this property from 0 to 1 which will give us easy access to a percent multiplier at every step of the animation.

var animate_to_degrees = 45;
$('#block').css({ orphans: 0 })
           .animate({ orphans: 1 }, {
             step: function(n, fx) {
               var cur_degrees = animate_to_degrees * n;
               var transform = 'rotateY('+cur_deg+'deg)';
               $(this).css({
                '-webkit-transform': transform,
                   '-moz-transform': transform,
                    '-ms-transform': transform,
                     '-o-transform': transform,
                        'transform': transform
               });
             }
             ,easing: 'easeInOutCubic'
             ,duration: 3000
           });

See the rotation in action

The step() function is called continuously as the animation is processed, with the value of n being a number between 0 and 1 which represents the percent of the animation that's been completed. If you wanted to animate in reverse you could go from 1 to 0, or just multiply cur_deg by -1.

Let's try a trickier one by animating a background color change.

var $block = $('#block');
var original_color = $block.css('background');

var animate_from = [];
var animate_to = [0, 0, 0]; // paint it black

// populate the animate_from array with the rgb() value
var color_value;
var color_value_regex = /([0-9]+)[,\)]/g;
while ((color_value = color_value_regex.exec(original_color)) !== null) {
  animate_from.push(+color_value[1]);
}

$block.css({ orphans: 0 })
      .animate({ orphans: 1 }, {
        step: function(n, fx) {
          // skip the first step (don't multiply by 0)
          if (n === 0) { return; }

          var color_step = [];
          for (var i = 0; i < 3; i++) {
            var step_value = n * (animate_to[i]
                                - animate_from[i]);

            // if the value is negative (decreasing)
            // use it to offset the original value
            if (step_value < 0) {
              step_value += animate_from[i];
            }

            // rgb() doesn't like floats
            color_step.push(parseInt(step_value, 10));
          }
          $(this).css({
            background: 'rgb(' +color_step.join()+ ')'
          });
        }
        ,easing: 'easeInOutCirc'
        ,duration: 5000
      });

See the color change in action

Ok, that last one got a little hairy. Still, you can see that by exploiting this trick you gain an easy way to animate pretty much any property (or combination of properties) according to a simple percentage value governed by any of the standard jQuery easing functions.

There are a lot of possibilities here, so I'd love to hear what you come up with.

Ciao!