Все таймеры в JavaScript основаны на стандартной функции JavaScript старой школы setInterval()
или setTimeout()
. Даже jQuery использует это внутренне.
Хитрость для синхронизации таймеров - убедиться, что вызывается только один setInterval()
, поэтому создайте что-то сами.
Анимация может быть разработана с:
Теперь, каждый раз, когда ваша функция вызывается 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();
Добавление паузы / резюме - упражнение для читателя.