我可以实现与jQuery的每个动画一步的回调? [英] Can I implement a callback with each animation step in jQuery?

查看:184
本文介绍了我可以实现与jQuery的每个动画一步的回调?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的地盘来实现的动画其中:


  • 需要更新多个DOM元素。

  • 每个DOM元素都有它自己的动画路径(取决于它们的位置)

  • ,仍然有一个宽松的效果。

如果我把jQuery的动画()函数的每个元素(队列:假的),就会使每个元素不同步,其余轻微移动。是有道理的,因为有运行多个定时器。

我可以只有一个计时器事件,以及每个动画一步的回调?
是这样的:

  jQuery.fx.timeline(从,到,缓和,功能(步,共){      VAR百分比=步/总;
      基于动画的百分比// ...更新DOM元素});


解决方案

在JavaScript中的所有定时器都基于本地普通的旧学校JavaScript函数的setInterval()的setTimeout()。即使jQuery使用这个内部。

诀窍同步计时器,是确保只有一个的setInterval()被调用,从而建立自己的东西。

这是动画可以被设计成具有:


  • 有10个步骤,每一个都具有30毫秒的间隔。

  • 总动画需要300毫秒。

  • 在每一步,目前的进展/百分比可以这样计算:

    VAR比例=(currentStep / totalSteps);


现在,每次你的函数是由的setInterval()调用,您可以设置一旦所有的DOM元素,以正确的位置。要找出一个元素应该是在每一个动画帧,可以使用:

  VAR差异=(来 - 从);
VAR stepValue =从+ DIFF *百分比;

jQuery的缓动函数,可以直接调用,而最后的陈述就变成了:

  VAR stepValue = jQuery.easing [easingMethod](百分比0,距离,差异);


我已经把这个变成一个类:

  / **
 *动画时间轴,用一个回调。
 * /
功能AnimationTimeline(参数,可以onstep)
{
  //复制值。  //要求:
  this.from = params.from || 0; //例如0%
  this.to = params.to || 1; //例如100%
  this.onstep = onstep || params.onstep; //通过回调。  //可选
  this.steps = params.steps || 10;
  this.duration = params.duration || 300;
  this.easing = params.easing || 线性;  //内部
  this._diff = 0;
  this._step = 1;
  this._timer = 0;
}jQuery.extend(AnimationTimeline.prototype,{  启动:功能()
  {
    如果(this.from == this.to)
      返回;    如果(this._timer大于0)
    {
      self.console&功放;&安培; console.error(双启动!);
      返回;
    }    VAR自己=这;
    this._diff =(this.to - this.from);
    this._timer =的setInterval(函数(){myself.doStep()},this.duration / this.steps);
  },止损:功能()
  {
    clearInterval(this._timer);
    this._timer = -1;
    this._queue = [];
  },doStep:功能()
  {
    从+ DIFF *百分比stepValue =;://的版本的jQuery
    VAR比例=(this._step / this.steps);
    变种stepValue = jQuery.easing [this.easing](百分比,0,this.from,this._diff);    // 下一步
    VAR道具= {animationId:this._timer + 10
                ,百分比:百分比
                来自:this.from到:this.to
                ,步:this._step,步骤:this.steps
                };
    如果(++ this._step> this.steps)
    {
      stepValue = this.to; //避免舍入误差。
      this.stop();
    }    // 回电话
    如果(this.onstep(stepValue,道具)=== FALSE){
      this.stop();
    }
  }
});

和现在你可以使用:

  VAR EL1 = $(#中element1);
VAR EL2 = $(#在element2);VAR动画=新AnimationTimeline({
    宽松:摇摆
  ,onstep:功能(stepValue,animprops)
    {
      //这就是所谓的每一个动画帧。设置的元素:
      el1.css({左:......,顶:...});
      el2.css({左:......,顶:...});
    }
  });//并启动它。
animation.start();

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

I'd like to implement an animation in my site which:

  • needs to update multiple DOM elements.
  • each DOM element has it's own animation path (depends on their position)
  • and still have an easing effect.

If I call jQuery's animate() function for each element (with queue: false), it will make each element move slightly out of sync with the rest. Makes sense, since there are multiple timers running.

Can I have just one timer event, with a callback for each animation step? Something like:

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

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

} );

解决方案

All timers in JavaScript are based on the native plain old school JavaScript function setInterval() or setTimeout(). Even jQuery uses this internally.

The trick to synchronize timers, is making sure there is only one setInterval() is invoked, so build something ourselves.

An animation can be designed with:

  • have 10 steps, each with an interval of 30ms.
  • The total animation takes 300ms.
  • At each step, the current progress/percentage can be calculated:

    var percentage = ( currentStep / totalSteps );

Now, each time your function is called by setInterval(), you can set all DOM elements at once to the correct positions. To find out where an element should be at each animation frame, you use the:

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

The jQuery easing functions can be called directly, and the final statement becomes:

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


I've turned this into a class:

/**
 * 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();
    }
  }
});

And now you can use:

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();

Adding a pause/resume is an exercise for the reader.

这篇关于我可以实现与jQuery的每个动画一步的回调?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆