假设你有一个很长的动画,你正在改变width
:
var myTargetWidth = 500;
$(el).animate( { "width" : myTargetWidth }, 5000 );
动画是异步的,因此您的代码将继续。. . 几秒钟后,您决定将目标更改width
为300
. . . 此时动画仍在运行。. .
如何在运行动画中将 targetWidth 更改为不同的值?
一种选择是使用jQuery函数 ( APIstep
)中提到的函数在动画运行时检查条件。animate
示例 JSFiddle:http: //jsfiddle.net/GweLA/13/
JS
var myTargetWidth = 500;
$(document).ready(function(){
$('.sample').animate( { "width" : myTargetWidth },{
duration : 5000,
step: function(now, fx) {
if($(this).width() > 200){
myTargetWidth = 300;
$(this).stop().animate({ "width" : myTargetWidth },1000);
}
}
});
});
CSS
.sample{
width:20px;
height:100px;
background-color:#cccccc;
}
HTML
<div class="sample">
width is supposed to be animated till 500 but it stops at 300
</div>
解决方案2:
经过一番研究,我发现我们可以修改传递给 step 函数的参数的start
和end
属性来控制动画。fx
这种平滑动画,但不是一种非常整洁的方式。
示例 JSFiddle:http: //jsfiddle.net/GweLA/57/
JS
var myTargetWidth = 500;
var isExecuted = false;
$(document).ready(function(){
$('.sample').animate( { "width" : myTargetWidth },{
duration : 5000,
queue : false,
step: function(now, fx) {
//So that fx.start and fx.end is set only once
if($(this).width() > 200 && $(this).width() < 203){
if(!isExecuted){
fx.start = now-65;
fx.end = 300;
}
isExecuted = true;
}
}
});
});
您可以使用.stop()的组合- 停止动画。
:animated选择器 - 检查当前元素是否正在动画..
试试这个
HTML
<div class="a">
</div>
<button id="check">Check Animation </button>
Javascript
var myTargetWidth = 300;
var $el = $('.a')
$el.animate({
"width": myTargetWidth
}, 5000);
$('#check').on('click', function() {
var newHeight = 300;
if ($('.a:animated')) {
$el.stop().animate({
"height": newHeight
}, 5000);
}
});
查看 jquery github 中的 effects.js,你会在赋值后更改变量时遇到问题
来源:https ://github.com/jquery/jquery/blob/master/src/effects.js
注意:注意 .animate 中的分配和对象创建到动画(工作马)
animate: function( prop, speed, easing, callback ) {
var empty = jQuery.isEmptyObject( prop ),
optall = jQuery.speed( speed, easing, callback ),
doAnimation = function() {
// Operate on a copy of prop so per-property easing won't be lost
var anim = Animation( this, jQuery.extend( {}, prop ), optall );
// Empty animations resolve immediately
if ( empty ) {
anim.stop( true );
}
};
return empty || optall.queue === false ?
this.each( doAnimation ) :
this.queue( optall.queue, doAnimation );
}
//在effects.js中动画
function Animation( elem, properties, options ) {
var result,
index = 0,
length = animationPrefilters.length,
deferred = jQuery.Deferred().always( function() {
// don't match elem in the :animated selector
delete tick.elem;
}),
tick = function() {
var currentTime = fxNow || createFxNow(),
remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
temp = remaining / animation.duration || 0,
percent = 1 - temp,
index = 0,
length = animation.tweens.length;
for ( ; index < length ; index++ ) {
animation.tweens[ index ].run( percent );
}
deferred.notifyWith( elem, [ animation, percent, remaining ]);
if ( percent < 1 && length ) {
return remaining;
} else {
deferred.resolveWith( elem, [ animation ] );
return false;
}
},
animation = deferred.promise({
elem: elem,
props: jQuery.extend( {}, properties ),
opts: jQuery.extend( true, { specialEasing: {} }, options ),
originalProperties: properties,
originalOptions: options,
startTime: fxNow || createFxNow(),
duration: options.duration,
tweens: [],
createTween: function( prop, end ) {
var tween = jQuery.Tween( elem, animation.opts, prop, end,
animation.opts.specialEasing[ prop ] || animation.opts.easing );
animation.tweens.push( tween );
return tween;
},
stop: function( gotoEnd ) {
var index = 0,
// if we are going to the end, we want to run all the tweens
// otherwise we skip this part
length = gotoEnd ? animation.tweens.length : 0;
for ( ; index < length ; index++ ) {
animation.tweens[ index ].run( 1 );
}
// resolve when we played the last frame
// otherwise, reject
if ( gotoEnd ) {
deferred.resolveWith( elem, [ animation, gotoEnd ] );
} else {
deferred.rejectWith( elem, [ animation, gotoEnd ] );
}
return this;
}
}),
props = animation.props;
propFilter( props, animation.opts.specialEasing );
for ( ; index < length ; index++ ) {
result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
if ( result ) {
return result;
}
}
createTweens( animation, props );
if ( jQuery.isFunction( animation.opts.start ) ) {
animation.opts.start.call( elem, animation );
}
jQuery.fx.timer(
jQuery.extend( tick, {
anim: animation,
queue: animation.opts.queue,
elem: elem
})
);
// attach callbacks from options
return animation.progress( animation.opts.progress )
.done( animation.opts.done, animation.opts.complete )
.fail( animation.opts.fail )
.always( animation.opts.always );
}
结果,我认为您将不得不 .stop 并使用更改的变量重新排列动画,因为您几乎没有希望访问闭包中的任何变量(请有人纠正我)
我在这里添加了一个示例:
尝试单击动画中的“单击此处”元素...
我使用clearQueue()
andstop()
函数。
CSS #block { 宽度:100px; 高度:100px;背景:红色;}</p>
HTML
<p>
<a id="clickme">Click here</a>
</p>
查询
$('#clickme').not('.again').on('mouseup',function() {
$(this).addClass('again');
$('#block').animate({
width: '400'
}, 5000, function() {
// Animation complete.
});
});
$('.again').live('mousedown', function() {
$(this).removeClass('again');
$('#block').clearQueue().animate({
width: '200',
}, 500, function() {
$('#block').stop(true, false);
});
});
<div id="block" />