JavaScript Animate
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.
大概意思就是使用JavaScript做动画比用JS库和CSS滤镜要好很多,这是一个兼容多数浏览器的实例。
<html lang="en"> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <title>JavaScript Animation Example</title> <script type="text/javascript"> /** * @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); }; /** * @static * @boolean * allows us to check if native CSS transitions are possible */ Animate.canTransition = function() { var el = document.createElement('twitter'); el.style.cssText = '-webkit-transition: all .5s linear;'; return !!el.style.webkitTransitionProperty; }(); </script> <style type="text/css"> a { color: blue; } #doc { width: 500px; font: 14px 'helvetica neue', helvetica, arial, sans-serif; margin: 0 auto; } #test { width: 300px; height: 300px; background-color: green; } </style> </head> <body> <div id="doc"> <p><a class="animated" href="#" id="click">click to test</a></p> <div id="test"></div> </div> <script type="text/javascript"> (function() { var blocking = false; document.getElementById('click').onclick = function(e) { if (blocking) { return false; } blocking = true; var that = this; var el = document.getElementById('test'); var from = this.className == 'animated' ? 1 : 0; var to = from == 1 ? 0 : 1; // relevant stuffs if (Animate.canTransition) { el.style.webkitTransition = 'opacity 0.5s ease-out'; el.style.opacity = to; blocking = false; that.className = that.className == 'animated' ? '' : 'animated'; } else { new Animate(el, 'opacity', { from: from, to: to, time: 500, callback: function() { that.className = that.className == 'animated' ? '' : 'animated'; blocking = false; } }).start(); }return false; }; }()); </script> </body> </html>