【问题标题】:Can I implement a callback with each animation step in jQuery?我可以在 jQuery 中为每个动画步骤实现回调吗?
【发布时间】:2010-11-24 13:55:10
【问题描述】:

我想在我的网站中实现一个动画:

  • 需要更新多个 DOM 元素。
  • 每个 DOM 元素都有自己的动画路径(取决于它们的位置)
  • 仍然有缓动效果。

如果我为每个元素调用 jQuery 的 animate() 函数(使用 queue: false),它将使每个元素的移动与其余元素略微不同步。有道理,因为有多个计时器在运行。

我可以只有一个计时器事件,每个动画步骤都有一个回调吗? 比如:

jQuery.fx.timeline( from, to, easing, function( step, total ) {

      var percentage = step / total;
      // ...update DOM elements based on the percentage of the animation

} );

【问题讨论】:

    标签: jquery animation effect timeline


    【解决方案1】:

    看这篇文章:http://james.padolsey.com/javascript/fun-with-jquerys-animate/

    很清楚,很容易!

    【讨论】:

    【解决方案2】:

    JavaScript 中的所有计时器都基于原生普通的老式 JavaScript 函数 setInterval()setTimeout()。甚至 jQuery 在内部也使用它。

    同步计时器的诀窍是确保只有一个setInterval() 被调用,所以我们自己构建一些东西。

    动画可以设计成:

    • 有 10 个步骤,每个步骤的间隔为 30 毫秒。
    • 整个动画耗时 300 毫秒。
    • 在每一步,都可以计算出当前的进度/百分比:

      var 百分比 = ( currentStep / totalSteps );

    现在,每次setInterval() 调用您的函数时,您可以一次将所有 DOM 元素设置到正确的位置。要找出元素在每个动画帧中的位置,请使用:

    var diff       = ( to - from );
    var stepValue  = from + diff * percentage;
    

    可以直接调用jQuery的缓动函数,最终语句变为:

    var stepValue  = jQuery.easing[ easingMethod ]( percentage, 0, from, diff );
    

    我已经把它变成了一个类:

    /**
     * Animation timeline, with a callback.
     */
    function AnimationTimeline( params, onstep )
    {
      // Copy values.
    
      // Required:
      this.from     = params.from || 0;         // e.g. 0%
      this.to       = params.to   || 1;         // e.g. 100%
      this.onstep   = onstep || params.onstep;  // pass the callback.
    
      // Optional
      this.steps    = params.steps    || 10;
      this.duration = params.duration || 300;
      this.easing   = params.easing   || "linear";
    
      // Internal
      this._diff  = 0;
      this._step  = 1;
      this._timer = 0;
    }
    
    jQuery.extend( AnimationTimeline.prototype, {
    
      start: function()
      {
        if( this.from == this.to )
          return;
    
        if( this._timer > 0 )
        {
          self.console && console.error("DOUBLE START!");
          return;
        }
    
        var myself  = this;    
        this._diff  = ( this.to - this.from );
        this._timer = setInterval( function() { myself.doStep() }, this.duration / this.steps );
      }
    
    , stop: function()
      {
        clearInterval( this._timer );
        this._timer = -1;
        this._queue = [];
      }
    
    , doStep: function()
      {
        // jQuery version of: stepValue = from + diff * percentage;
        var percentage = ( this._step / this.steps );
        var stepValue  = jQuery.easing[ this.easing ]( percentage, 0, this.from, this._diff );
    
        // Next step
        var props = { animationId: this._timer + 10
                    , percentage: percentage
                    , from: this.from, to: this.to
                    , step: this._step, steps: this.steps
                    };
        if( ++this._step > this.steps )
        {
          stepValue = this.to;  // avoid rounding errors.
          this.stop();
        }
    
        // Callback
        if( this.onstep( stepValue, props ) === false ) {
          this.stop();
        }
      }
    });
    

    现在你可以使用:

    var el1 = $("#element1");
    var el2 = $("#element2");
    
    var animation = new AnimationTimeline( {
        easing: "swing"
      , onstep: function( stepValue, animprops )
        {
          // This is called for every animation frame. Set the elements:
          el1.css( { left: ..., top: ... } );
          el2.css( { left: ..., top: ... } );
        }
      });
    
    // And start it.
    animation.start();
    

    添加暂停/恢复是读者的练习。

    【讨论】:

      【解决方案3】:

      一个简单的答案。也许有人会像我一样搜索它。

      我们可以在动画函数中使用“step”属性。

      $(obj).animate(
          {
              left: 0
          },
          {
              duration: 50,
              step: function( currentLeft ){
                  console.log( "Left: ", currentLeft );
              }
          }
       );
      

      所以对于每一步,这都会记录当前的左侧位置

      【讨论】:

      • 啊,现在看来 jQuery 已经支持了。好的! :)
      【解决方案4】:

      你检查jquery queue了吗?

      您可以对动画进行排队并在每个动画上设置回调,我认为如果您稍微玩一下它就可以实现您想要的。

      希望对你有帮助,思南。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多