4 Stimmen

Kann ich einen Rückruf mit jedem Animationsschritt in jQuery implementieren?

Ich möchte eine Animation in meine Website einbauen, die:

  • mehrere DOM-Elemente aktualisieren muss.
  • jedes DOM-Element hat seinen eigenen Animationspfad (abhängig von seiner Position)
  • und dennoch eine lindernde Wirkung haben.

Wenn ich die Funktion animate() von jQuery für jedes Element aufrufe (mit queue: false), bewegt sich jedes Element etwas anders als der Rest. Macht Sinn, da es mehrere Timer ausgeführt werden.

Kann ich nur ein Timer-Ereignis haben, mit einem Callback für jeden Animationsschritt? Etwas wie:

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

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

} );

4voto

Sehen Sie sich diesen Artikel an: http://james.padolsey.com/javascript/fun-with-jquerys-animate/

sehr klar, sehr einfach!

1 Stimmen

Schöner Fund! Viel einfacher als die "beste Antwort".

0 Stimmen

Dieser Link ist tot, aber der Inhalt ist verfügbar unter web.archive.org/web/20200925113411/https://j11y.io/javascript/

4voto

vdboor Punkte 20756

Alle Timer in JavaScript basieren auf der JavaScript-Funktion der alten Schule setInterval() o setTimeout() . Auch jQuery verwendet dies intern.

Der Trick bei der Synchronisierung von Timern besteht darin, sicherzustellen, dass es nur einen setInterval() aufgerufen wird, also bauen Sie selbst etwas.

Eine Animation kann mit gestaltet werden:

  • haben 10 Schritte mit einem Abstand von jeweils 30 ms.
  • Die gesamte Animation dauert 300 ms.
  • Bei jedem Schritt kann der aktuelle Fortschritt/Prozentsatz berechnet werden:

    var percentage = ( currentStep / totalSteps );

Jedes Mal, wenn Ihre Funktion nun von setInterval() können Sie alle DOM-Elemente auf einmal an die richtige Position setzen. Um herauszufinden, wo sich ein Element bei jedem Animationsframe befinden sollte, verwenden Sie die Funktion:

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

Die jQuery-Easing-Funktionen können direkt aufgerufen werden, und die letzte Anweisung wird:

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

Ich habe daraus einen Kurs gemacht:

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

Und jetzt können Sie es benutzen:

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

Das Hinzufügen einer Pause/eines Resümees ist eine Übung für den Leser.

4voto

Mike Boutin Punkte 5178

Eine einfache Antwort, um es zu tun. Vielleicht wird jemand es suchen, wie ich es tat.

Wir können das Attribut "step" in der Animationsfunktion verwenden.

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

Für jeden Schritt wird also die aktuelle linke Position aufgezeichnet

0 Stimmen

Ah, es scheint jQuery hat Unterstützung für die jetzt. nett! :)

1voto

Sinan Punkte 11173

Haben Sie geprüft jquery-Warteschlange ?

Sie können Ihre Animationen in eine Warteschlange stellen und für jede von ihnen einen Rückruf festlegen. Ich denke, wenn Sie ein wenig damit spielen, können Sie erreichen, was Sie wollen.

Ich hoffe, das hilft, Sinan.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X