代码之家  ›  专栏  ›  技术社区  ›  vdboor

我可以在jquery中对每个动画步骤实现回调吗?

  •  2
  • vdboor  · 技术社区  · 17 年前

    我想在我的站点中实现一个动画,它:

    • 需要更新多个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
    
    } );
    
    4 回复  |  直到 13 年前
        1
  •  5
  •   Tom    17 年前

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

    非常清楚,非常简单!

        2
  •  4
  •   vdboor    14 年前

    javascript中的所有计时器都是基于本地普通的老式javascript函数 setInterval() 或 setTimeout() . 甚至jquery也在内部使用它。

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

    动画可以设计为:

    • 每10步,间隔30毫秒。
    • 整个动画需要300毫秒。
    • 在每个步骤中,可以计算当前进度/百分比:

      var百分比=(currentstep/totalsteps);

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

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

    可以直接调用jquery easing函数,最后一条语句变为:

    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
  •  2
  •   Mike Boutin    13 年前

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

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

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

    因此,对于每个步骤,这将记录当前的左侧位置

        4
  •  1
  •   Sinan    17 年前

    你检查过了吗? jquery queue ?

    你可以把你的动画排成一列,然后对每一个都设置一个回调,我想如果你对它稍加利用,你就可以实现你想要的。

    希望能有所帮助,西南。