我可以在jQuery中的每个动画步骤中实现回调吗?
我想在我的网站上实现一个动画:
- 需要更新多个DOM元素。
- 每个DOM元素都有自己的动画路径(取决于它们的位置)
- 并且仍然有缓和效果。
如果我为每个元素调用jQuery的animate()函数(使用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 } );
看看这篇文章: http : //james.padolsey.com/javascript/fun-with-jquerys-animate/
很清楚,很容易!
JavaScript中的所有计时器都基于原生普通老式JavaScript函数setInterval()
或setTimeout()
。 甚至jQuery也在内部使用它。
同步定时器的技巧是确保只调用一个setInterval()
,所以自己构建一些东西。
动画可以设计为:
- 有10个步骤,每个步骤间隔30ms。
- 总动画需要300毫秒。
-
在每个步骤中,可以计算当前进度/百分比:
var percentage =(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; // eg 0% this.to = params.to || 1; // eg 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();
添加暂停/恢复是读者的练习。
这是一个简单的答案。 也许有人会像我一样搜索它。
我们可以在动画function中使用“step”属性。
$(obj).animate( { left: 0 }, { duration: 50, step: function( currentLeft ){ console.log( "Left: ", currentLeft ); } } );
因此,对于每个步骤,这将记录当前的左侧位置
你检查了jquery队列吗?
你可以对你的动画进行排队并在每个动画上设置一个回调,我想如果你玩它很少,你可以实现你想要的。
希望它有所帮助,思南。