I am trying to detect when the user scrolls down on a page, so i can animate the height of a div. When the user is at the top of the page the #header is 100px, and once they scroll it becomes 50px. Here is my code:
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 10) {
$('#header').animate({height: "50px"});
} else {
$('#header').animate({height: "100px"});
}
});
The above works, but when the user scrolls back to the top, there is a slight delay before the height animation happens.
Any ideas?
window onscroll is called multiple times so you are triggering animate multiple times. This is causing multiple animations to be running at the same time. You need to cancel the previous animation with stop() before triggering the next.
$(window).scroll(function() {
var scrollTop = $(this).scrollTop();
var height = (scrollTop >= 10) ? "50px" : "100px";
$('#header').stop().animate({height: height});
});
Now another thing you can do is track the last height and if .is(':animated') is running, than do not bother calling it again. It would still require .stop()
I think the default duration is 400ms, maybe that is causing a visual delay. Have you tried NOT animating the height and just setting it via .css('height', '50px') instead?
at the very least that will tell you if its the animate() call causing the delay or the window.scroll event handler...
Related
So what I want to know is how can I scroll the page down smoothly as I resize a div past the bottom of the browser.
So far what I have set up is that when you resize the div and it gets to the last 30px of of the browser, it starts to scroll the page down. That part works, but it's jerky when doing so.
My code:
// $maxHeight is set above this, it just takes all the elements within the div and and get's the total height and set that as maxHeight
$('.notifications-drop-down').resizable({
maxHeight: $maxHeight,
minHeight: 400,
handles: {
's': '.ui-resizable-s'
},
resize: function(event, ui){
if((ui.position.top + ui.size.height) > ($(window).scrollTop() + $(window).height() - 30)){
$(window).scrollTop($(window).scrollTop()+10);
}
}
});
What I tried to fix this:
Adding an animate function to the scrollTop to make it smoother
$('html,body').animate({scrollTop: $(window).scrollTop()+30}, 200);
But that does not work smoothly. I have changed the animation duration and it's still not smooth. Does anyone know what I can do it get this to be smooth?
Something I noticed was that when the page scrolls down it does not recognize that the div is in the bottom 30px so it's not recalculating if it should scroll down more (you need to wiggle your cursor while resizing the div for it to work), I did try and add the same code for scrolling down to the resizable's stop function but that didn't help as well.
Thanks for the time.
Hello i have a problem with my navbar.
I want to animate it on scroll and change his height. When i scroll a bit down it should animate smaller and when im at the top of the page it should aniamte bigger. The standard height is 100px. The problem is when im at the top of the page it takes a delay, which i need to wait, until it animates. They delays gets longer if i scroll first to the bottom of the page and then back to the top. The has a height of 11000px. This is my code for it:
$(document).on("scroll",function(){
if($(document).scrollTop()>500)
{
$( ".navbar" ).animate({height: 50} ,{duration:100});
}
else if($(document).scrollTop()==0)
{
alert("dhsihsp");
$( ".navbar" ).animate({height: 100} ,{duration:100});
}
});
Maybe u can help me. I use Google Chrome and Bootstrap 3.
The problem you are having is that the "scroll" fires every single time the scrollbar moves. So every single time the scrollbar moves a pixel, it will do the IF checks. That's why you delay your animation for so long. The queue of things to run stacks up immensely if you move the scrollbar too much.
DEMO
The scroll event seems to fire a lot when you scroll so all the events get queued. So the event that actually changes you header seems to take a long time to appear.
I added a css transition on the height of a .navbar. for making this happen almost instantly. Are the events not still there? True, but changing css is a lot less demanding then adding animations (with a duration of 100ms). The transition does have a duration but it does not have to finish so an other event can come in at any time.
CSS
.navbar {
transition: height 0.1s;
}
Jquery
$(window).scroll(function () {
var scrollh = $(this).scrollTop();
if (scrollh == 0) {
$(".navbar").css({
'height':'100px',
});
} else {
$(".navbar").css({
'height':'50px',
});
}
});
I have it set to a div's width increases when I scroll past it with the following code. Now I do this same thing except with .fadeIn() and it works fine. But when I use the .animate() i'll scroll to that location and nothing will happen, but like randomly 30-40 seconds later it will just decide to animate without me even touching/moving anything. Any reason why that is?
HTML
<div>
2500px of CONTENT
</div>
<div class="statbar"></div>
CSS
.statbar {
width:100px;
height:30px;
background-color:#ff4200;
}
jQuery
$(document).scroll(function () {
var y = $(this).scrollTop();
if (y > 2500) {
$('.statbar').animate({width:'200px'}, 300);
} else {
$('.statbar').animate({width:'10px'}, 300);
}
});
Here's a JSFiddle example: https://jsfiddle.net/kr4yeyw3/2/
If you wait like 30 seconds at the div, you'll see the animation will take place (need it to happen instantly like the fadeIn() does.
EDIT: It works when I change those 300 to zeros, but it doesn't animate! Just changes width instantly without "sliding" it over.
EDIT2: Finally figured it out for anyone who one day scrolls across this page looking for a similar answer.
Adding clearQueue(), stop() and easing seemed to do the trick
$('.statbar').clearQueue().stop().animate({width:'75%'}, { "duration": 400, "easing": "linear" });
clearQueue or Stop will do fix the animation, but it doesn't address the real problem with your code. In your else statement, which is hit like 2000 times as you scroll to the bottom of the page, you are starting an animation with a duration of 400 milliseconds.
jQuery animate puts all animations into a queue and calls them one after the other so it creates a huge delay before the animation you actually want to see. api.jquery.com/animate/
Here's how I think you should rework your code:
var isExpanded = false;
$(document).scroll(function () {
var y = $(this).scrollTop();
if (y > 2500) {
$('.statbar').animate({width:'200px'}, 300);
isExpanded = true;
} else if(isExpanded) {
$('.statbar').animate({width:'10px'}, 300);
isExpanded = false;
}
});
Here I use a flag to determine if the animation needs to be run and just toggle it as we switch display modes.
I am trying to recreate the effect seen here: http://jsfiddle.net/surendraVsingh/aATHd/2/
But I am trying to animate the height. For some reason, it works fine when I scroll down, but upon scrolling up, the height doesn't change back to normal. Any ideas?
Here is what I have now: http://justinledelson.com/new/
$(window).scroll(function(){
if ($(this).scrollTop() > 250){
$('#header').animate({"height":"100px"}, 1500);
}
else{
$('#header').animate({"height":"470px"}, 1);
}
});
Thanks!
Although I said that this wasn't a solution for your problem, it seems that it's actually a solution.
Add a class after each action. Something like expanded and collapsed for each situation, and check if that class is present before doing the animation. That way the animations won't trigger until it's necessary.
This avoids triggering the animation multiple times queuing the animation. That's why if you scrolled down a lot of times and scrolled back to top, the "expanding" animation triggered long after you scrolled up (it had to wait that each "collapsing" animation ended)
My test was:
$(window).scroll(function(){
var $header = $('#header');
if ($(this).scrollTop() > 50){ // x should be from where you want this to happen from top//
if (!$header.hasClass('collapsed')) {
$header.animate({"height":"100px"}, 1500, function() {
$header.toggleClass('expanded collapsed');
});
}
}
else{
if (!$header.hasClass('expanded')) {
$header.animate({"height":"470px"}, 1, function() {
$header.toggleClass('expanded collapsed');
});
}
}
});
header should start with expanded class
I have a navigation container near the top of the page that should add or remove the classname "stuck" (switching between position:static and position:fixed) when the page scrolls beyond a certain value. Seems to work fine in FF and Chrome, but of course IE (7,8 and 9) is having trouble.
The page lags heavily (essentially unusable) when scrolling using the mousewheel, although if I grab and drag the horiz scrollbar then the page slides smoothly with no lag.
My searching around revealed that it's probably because IE executes way more scroll events than the other browsers, but I can't figure out exactly how to throttle the number of events being fired. You can see in the code block below that I'm also using a 'scroll stop' solution but I really need to also be able to execute a callback WHILE the user is still scrolling when they go beyond a certain point on the page.
I thought the way I was implementing it was pretty and stripped down and basic, but is there a better way to handle this, at least just for IE?
var scrollValue = 0;
var scrollTimer = false;
$(window).bind('scroll', function(){
scrollValue = $(window).scrollTop();
// SET TIMER DELAY FOR SCROLL-STOP
if (scrollTimer) {
clearTimeout(scrollTimer);
}
scrollTimer = setTimeout(scrollStopped, 25);
// STICK/UNSTICK HEADER
if (scrollValue > 320){
if (!$(stickyWrap).hasClass('stuck')){
$(stickyWrap).addClass('stuck')
}
} else {
if ($(stickyWrap).hasClass('stuck')){
$(stickyWrap).removeClass('stuck');
}
}
});
Down with timeout, up with switch
If you made the jQuery a little more simple, and added a switch to only execute anything once before and after the threshold, it should speed things up nicely.
var header = $('.stickyWrap'),
trig = 320,
go = true;
$(window).bind('scroll', function(){
var scrollValue = $(this).scrollTop();
if ((go && scrollValue > trig) || (!go && scrollValue <= trig)) {//before or after
header.toggleClass('stuck');//toggle class
go ? go = false : go = true;//toggle boolean
}
});
Now it will only try to execute anything only once before and once after it crosses the threshold of 320.
Made A Fiddle >