jquery animate running laggy
I am trying to create a flashing arrow. However when I execute this script in different browsers it behaves badly. IE says its out of memory, Chrome lags for a second and then behaves well and in firefox t开发者_Go百科he animation is sticky.
Hope someone can work out a way that I can animate a flashing arrow smoothly. Thanks
aniPointer($('#arrow'));
function aniPointer(point) {
point.animate({opacity: 1.0}, {duration: 300})
.animate({opacity: 0.2}, {duration: 700})
.animate({opacity: 0.2}, {duration: 300})
.animate({opacity: 1.0}, {duration: 300, complete: aniPointer(point)})
}
You're creating an infinite loop. You did so intentionally, but its running a lot faster than you think. complete
takes a function reference. By adding the parens to the name of the callback function you are invoking aniPointer
immediately and passing the return value to complete
instead of passing a reference to aniPointer
itself to be fired at some later time.
Even so, is that sequence really what you want to do?
You're doing:
go to 1.0 over 300ms
go to 0.2 over 700ms
go to 0.2 over 300ms
go to 1.0 over 300ms
repeat
Assuming you're starting at 1.0 this is actually:
wait 300ms
go to 0.2 over 700ms
wait 300ms
go to 1.0 over 300ms
repeat
If you're looking for a steady pulse you could do something like this:
function pulse($elem) {
return window.setInterval(function() {
$elem.animate({opacity: 0.2}, 700)
.animate({opacity: 1.0}, 300);
}, 1000);
}
Or if you were pausing intentionally you could do:
function pulse($elem) {
return window.setInterval(function() {
$elem.animate({opacity: 0.2}, 700);
window.setTimeout( function() {
$elem.animate({opacity: 1.0}, 300);
}, 1000);
}, 1600);
}
The return value would allow you to stop the animation if you wanted to like so:
var pulseIntervalId = pulse( $('#arrow_id') );
//some time later...
window.clearInterval(pulseIntervalId);
Either version would skirt the infinite loop issue, allowing the callback to have the reference to the pulsing element without being invoked prematurely.
jasongetsdown's answer, although technically correct, is not very jQuery-esque. It also has the problem that if the animate
takes slightly longer than it ought to, the window.setTimeout
won't care and run a second instance in parallel, which might lead to all sorts of problems, so it's better to wait for the completion of the animate call before triggering a new one.
Here's another solution :
$.fn.pulse = function(lowOpacity, highOpacity) {
if (isNaN(+lowOpacity)) lowOpacity = 0.2;
if (isNaN(+highOpacity)) highOpacity = 1;
var that = this;
(this)
.delay(300)
.animate({opacity: lowOpacity}, 700)
.delay(300)
.animate({opacity: highOpacity}, 300, function() { that.pulse(lowOpacity, highOpacity); });
}
To use it you would do :
$('#elem').pulse();
To stop it you would do :
$('#elem').stop().clearQueue();
精彩评论