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.
Related
I'm trying to display a div after scroll animation has finished and hide it when I scroll up/down the page. This is my attempt:
$('#cta').on('click', function(e) {
e.preventDefault();
$('#layer, #servicesContent').addClass('active');
var position = parseInt($('#services').offset().top);
$('html, body').animate({
scrollTop: position - 100
}, 'slow', function() {
$(window).bind('scroll', function() {
$('#layer, #servicesContent').removeClass('active');
});
});
});
it doesn't work. the active class is removed after animation has finished and not with scroll movement.
Any idea?
Thanks in advance
Not exactly sure why, but apparently it takes the window somewhere around 20 milliseconds to exit the scroll state, at least on Chrome, on Windows. Or it might be a jQuery trick to fire the animation function 20ms sooner, so it feels more natural. (Human eye and mind make connections that take tiny amounts of time and maybe they took it into account).
Anyway, in order to make sure you bind after the scroll has ended, give it a full 100ms to finish and bind afterwards:
$('#cta').on('click', function(e) {
e.preventDefault();
$('#layer, #servicesContent').addClass('active');
var position = 120;
$('html, body').animate({
scrollTop: position - 100
}, 'slow', function() {
setTimeout(function(){
$(window).bind('scroll', function() {
$('#layer, #servicesContent').removeClass('active');
});
},100)
});
});
working fiddle.
Please note I had hard-coded a value to position, as #services is not defined in my example.
Also please note that hiding events on scroll is a really bad idea in terms of usability. Users might want to scroll so they view the div better or read it in full, but they will end up hiding it, which would be annoying. I would at least check the scroll event for a minimum velocity or distance in order to hide an element from the screen.
SCENARIO
I have developed a function with jQuery which listens to the user's mouse input (based on the mousewheel plugin).
I analyze the user's input with a function, and alter the default behavior of the mouse, so that it scrolls a given px value with an animation.
PROBLEM
There are div containers in the webpage that transform its size when hovered.
This causes my original mousewheel animation to delay its action for a little time (more or less, half a second). If a div is hovered, and quickly afterwards the mousewheel is rolled, the effect won't run 100% smoothly (it will cause a little lag while the scroll animation is executing, and right afterwards, it will show the animation, which was already running).
If I delete the transition in the containers, the problem is solved. However, I would like to keep the original CSS intact, and run my original animation smoothly.
How can I accomplish this?
JSFIDDLE
http://jsfiddle.net/kouk/z7p0vxpg/
JS CODE
$(function () {
function wheel($div, deltaY) {
if (deltaY == -1) {
var dest = ($(document).scrollTop()+500);
$('html,body').animate({scrollTop: dest}, 1000);
return false;
} else if (deltaY == 1) {
var dest = ($(document).scrollTop()-500);
$('html,body').animate({scrollTop: dest}, 1000);
return false;
}
}
$('html').bind('mousewheel', function (event, delta, deltaX, deltaY) {
if ($('html,body').is(":animated")){
return false;
}
if ( (delta > -2) && (delta < 2) ) {
wheel($(this), deltaY);
event.preventDefault();
console.log(delta);
}
});
});
This is a common problem with the animate() function. The previous animations are in the queue and lagging behind. You should empty the animation queue before starting the next animation to avoid the "lag" feeling.
There are two functions which let you do that : finish() and stop() . I recommend using finish as it will stop the running animation )and remove all queued animations. This was you can immediately start your latest animation.
A user doesn't necessarily want to wait for his previous animation which he has already started a new action.
Here's some sample code:
$('html,body').dequeue().animate({scrollTop: dest}, 1000);
See if the behavior is as your expected now.
And your code (updated with finish()) - http://jsfiddle.net/z7p0vxpg/15/
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 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
The following code, will make the "Go to top" button fade in when the scrollTop() is over 400px, that works fine, but i haven't found a way to make it fade out when i go back to the top.
$("#gototop").css("opacity", "0");
$(window).bind('scroll', function(){
if($(this).scrollTop() > 400) {
$("#gototop").animate({
opacity: 100,
}, 3400);
}
});
An else after the if didn't help, i tried different options with my non-ninja skills but none worked. Any ideas on how to make it fade out when the scroll is back at the top?
Thanks.
Something along the lines of either an additional scroll handler that does the opposite or another if inside your first handler should do it (you want to test if scrollTop() < 400.
$(window).bind('scroll', function(){
if($(this).scrollTop() < 400) {
$("#gototop").animate({
opacity: 0,
}, 3400);
}
});
Note though, that this is animating it on every call to the scroll event, you probably only want to do it once (when the scroll passes the 400px threshold) so maybe add a variable to record the current state of #gototop.
if(visible && $(this).scrollTop() < 400) {
visible = !visible;
//animate
}
I ended up using a plugin called waypoints to handle the scroll position.