我可以实现与jQuery的每个动画一步的回调? [英] Can I implement a callback with each animation step in 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屋!