Reputation: 693
I'm having troubles getting this code to execute in a timely manner in Firefox. It seems to work just fine in Chrome.
JSFiddle here: http://jsfiddle.net/EXDhb/
Real live example page I'm working with here: http://mindevo.com/tests/tacos.html
I'm not sure if I'm leaving something out. I kind of hacked this together from reading a bunch of page-scroll scripts other people have put together. Not sure if this is even the best way for me to do what I'm trying to accomplish (which is to darken the next area until it's somewhat revealed. (I used halfway for this).
Here's my javascript:
$(document).ready(function(){
$(window).scroll(function(){
$('.dark').each(function(i){
var half_object = $(this).position().top + ($(this).outerHeight()/2);
var bottom_window = $(window).scrollTop() + $(window).height();
var bottom_object = $(this).position().top + $(this).outerHeight();
if(bottom_window > half_object){
$(this).animate({'opacity':'1'},200);
}
else if(bottom_object > $(window).scrollTop()) {
$(this).animate({'opacity':'.5'},200);
}
});
});
});
Is there a better way to do this? I tried adding/removing css classes but it invoked some crazy Chrome bug I was not pleased about.
Why does it work so slowly in Firefox?
Upvotes: 0
Views: 99
Reputation: 93601
Start by not having 6 separate jQuery $(this)
operations and multiple $(window)
! Use temp variables whenever you can to avoid requerying.
JSFIddle: http://jsfiddle.net/TrueBlueAussie/EXDhb/9/
$(document).ready(function () {
// window never changes
var $window = $(window);
$window.scroll(function () {
// Window height may have changed between scrolls
var windowHeight = $window.height();
var scrollTop = $window.scrollTop();
$('.dark').each(function (i) {
var $this = $(this);
var top = $this.position().top;
var outerH = $this.outerHeight();
var half_object = top + (outerH / 2);
var bottom_window = scrollTop + windowHeight;
var bottom_object = top + outerH;
console.log(half_object);
if (bottom_window > half_object) {
$this.stop().animate({
'opacity': '1'
}, 200);
} else if (bottom_object > scrollTop) {
$this.stop().animate({
'opacity': '.5'
}, 200);
}
});
});
});
And so on until you do not do anything twice that has an overhead that you do not need to have.
The pause was not caused by the speed of the code above, but by not stopping multiple animations. The problem is that scroll
fires frequently, so without .stop()
animations get queued up and fire one after the other. This made it look much slower that it actually was.
Further optimizations might involve only processing elements that are actually onscreen, but that is pretty pointless given the apparent speed now.
Upvotes: 2
Reputation: 18868
I realize there is already an accepted answer, but many times it is useful to do something only after the user has stopped scrolling, and not each time the "scroll" event fires. This event can can fire upwards of 50 times per second, leaving you with ~20ms to do what you need to do. This other StackOverflow question shows you how to do something only after scrolling has stopped. As @TrueBlueAussie mentioned in his answer, you would still want to stop any animations that were currently running.
Upvotes: 1
Reputation: 34011
You can cache your variables, which should help slightly:
$(document).ready(function(){
var $window = $(window);
$window.scroll( function(){
$('.dark').each(function(i){
var $this = $(this);
var outerHeight = $this.outerHeight();
var positionTop = $this.position().top;
var half_object = positionTop + (outerHeight/2);
var bottom_window = window.scrollTop() + window.height();
var bottom_object = positionTop + outerHeight;
if(bottom_window > half_object){
$this.animate({'opacity':'1'}, 200);
} else if(bottom_object > window.scrollTop()) {
$this.animate({'opacity':'.5'}, 200);
}
});
});
});
Upvotes: 1