i am dustin diaz

a JavaScriptr...

boosh.

don't worry about it.

JavaScript Animate

Saturday Jul 3 2010

Sort of an old topic for these times, but I thought I'd share a small snippet I wrote about a year ago for the live updating Twitter widgets which required a tad bit of animation without the use of a library. Of course, anyone doing a large amount of animation will use some JavaScript library or, when available in a browser - CSS transitions. Ultimately, the goal for the widgets - which would end up on thousands of websites, was to make them as lightweight as possible - so you can't just go around and make jQuery, YUI, or Prototype a requirement. Thus, a simple animation class was in order. One that will work in any browser that supports JavaScript - and can animate any CSS property that is enumerable. Eg: height, weight, font-size, top, left... not color, background-image, text-decoration, etc.

Animation class

/**

  * @constructor Animate

  * @param {HTMLElement} el the element we want to animate

  * @param {String} prop the CSS property we will be animating

  * @param {Object} opts a configuration object

  * object properties include

  * from {Int}

  * to {Int}

  * time {Int} time in milliseconds

  * callback {Function}

  */

function Animate(el, prop, opts) {

  this.el = el;

  this.prop = prop;

  this.from = opts.from;

  this.to = opts.to;

  this.time = opts.time;

  this.callback = opts.callback;

  this.animDiff = this.to - this.from;

}



/**

  * @private

  * @param {String} val the CSS value we will set on the property

  */

Animate.prototype._setStyle = function(val) {

  switch (this.prop) {

    case 'opacity':

      this.el.style[this.prop] = val;

      this.el.style.filter = 'alpha(opacity=' + val * 100 + ')';

      break;



    default:

      this.el.style[this.prop] = val + 'px';

      break;

  };

};



/**

  * @private

  * this is the tweening function

  */

Animate.prototype._animate = function() {

  var that = this;

  this.now = new Date();

  this.diff = this.now - this.startTime;



  if (this.diff > this.time) {

    this._setStyle(this.to);



    if (this.callback) {

      this.callback.call(this);

    }

    clearInterval(this.timer);

    return;

  }



  this.percentage = (Math.floor((this.diff / this.time) * 100) / 100);

  this.val = (this.animDiff * this.percentage) + this.from;

  this._setStyle(this.val);

};



/**

  * @public

  * begins the animation

  */

Animate.prototype.start = function() {

  var that = this;

  this.startTime = new Date();



  this.timer = setInterval(function() {

    that._animate.call(that);

  }, 4);

};
The background on its design was from a technique Y.U.I. came up with in its initial launch in the Animation internals. It's time-based, overclocked, and plays catchup for browsers that tend to run slower. Hence, the animation looks smoother in faster browsers, but does not get ahead of itself.

Bonus

Use transitions when possible. Generally speaking, the faster browsers tend to be ahead of their time anyway, and provide an alternative to animations with CSS transitions - so why not take advantage of this.

transition

/**

  * @static

  * @boolean

  * allows us to check if native CSS transitions are possible

  */

Animate.canTransition = function() {

  var el = document.createElement('foo');

  el.style.cssText = '-webkit-transition: all .5s linear;';

  return !!el.style.webkitTransitionProperty;

}();
How does it all work in practice?

Fade In Example

if (Animate.canTransition) {

  el.style.webkitTransition = 'opacity 0.5s ease-out';

  el.style.opacity = 1;

}

new Animate(el, 'opacity', {

  from: 0,

  to: 1,

  time: 500,

  callback: done

}).start();
In the end, it's barebones, but works efficiently. If you need more out of it, tweak it to your liking, or really, just use a library – which won't be uncommon.

Oh right, yeah, almost forgot - these wouldn't be proper without a demo page. Cheers.

this is who i am

Hi, my name is Dustin Diaz. Nice to meet you, too. I (actually) build products. Currently founder of an Expa-backed company. Previously @Change, @Medium, @Twitter, @Google, and @Yahoo. I wrote a book called Strobist® Info and was co-author of JavaScript Design Patterns. I co-created the Ender JavaScript Framework, I was an award-winning Photographer, and I pretend to be an amateur Mixologist. Pretend is fun. This is my website. Welcome!

On this site I (used to) write about JavaScript. You can also follow along with my open-source work on Github.

Last but not least, recruiters, you are very kind. I’m not looking for work. Cheers.