假设您有一个很长的动画,您正在更改width
:
var myTargetWidth = 500;
$(el).animate( { "width" : myTargetWidth }, 5000 );
动画是异步的,因此您的代码会继续。 。 。
几秒钟后,您决定将目标width
更改为300
。 。 。
此时动画仍在运行。 。
如何在正在运行的动画中将targetWidth更改为其他值?
答案 0 :(得分:4)
一种选择是使用jQuery step
函数(API)中提到的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;
}
}
});
});
答案 1 :(得分:2)
您可以结合使用 .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);
}
});
<强> Check Fiddle 强>
答案 2 :(得分:0)
在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 );
}
结果我认为你必须使用已更改的变量停止和重新排队动画,因为你几乎没有希望访问闭包中的任何变量(请有人纠正我)
答案 3 :(得分:0)
我在这里添加了一个例子:
尝试点击动画中的“点击此处”元素...
我使用clearQueue()
和stop()
函数。
CSS #block {width:100px;身高:100px;背景:红色; }
HTML
<p>
<a id="clickme">Click here</a>
</p>
JQUERY
$('#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" />