Могу ли я реализовать обратный вызов с каждым шагом анимации в jQuery? - PullRequest
2 голосов
/ 01 сентября 2009

Я бы хотел реализовать анимацию на моем сайте, которая:

  • необходимо обновить несколько элементов DOM.
  • каждый элемент DOM имеет свой собственный путь анимации (зависит от их положения)
  • и по-прежнему имеют эффект ослабления.

Если я вызову функцию animate () jQuery для каждого элемента (с 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 ]

5 голосов
/ 24 сентября 2009

посмотрите на эту статью: http://james.padolsey.com/javascript/fun-with-jquerys-animate/

очень ясно, очень легко!

4 голосов
/ 04 декабря 2009

Все таймеры в JavaScript основаны на стандартной функции JavaScript старой школы setInterval() или setTimeout(). Даже jQuery использует это внутренне.

Хитрость для синхронизации таймеров - убедиться, что вызывается только один setInterval(), поэтому создайте что-то сами.

Анимация может быть разработана с:

  • имеет 10 шагов, каждый с интервалом 30 мс.
  • Полная анимация занимает 300 мс.
  • На каждом шаге можно рассчитать текущий прогресс / процент:

    процентное соотношение = (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();

Добавление паузы / резюме - упражнение для читателя.

2 голосов
/ 04 апреля 2013

Простой ответ, чтобы сделать это. Может быть, кто-то будет искать это, как я.

Мы можем использовать атрибут «step» в функции анимации.

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

Таким образом, для каждого шага будет записываться текущее левое положение

1 голос
/ 01 сентября 2009

вы проверяли очередь запросов ?

Вы можете ставить в очередь свои анимации и устанавливать обратный вызов для каждой из них, я думаю, что если вы немного поиграете с этим, вы сможете добиться того, чего хотите.

Надеюсь, это поможет, Синан.

...