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>
posted @ 2010-09-23 23:27  e.e.p  阅读(2306)  评论(0编辑  收藏  举报