I've build a sticky navigation that disappears when the user scrolls down, and re-appears when he/she scrolls back up. This is so there's more content visible on smaller screens when, for example, reading an article.
The problem I had was animations queue build-up, but I was able to fix it using .stop()
However, this created another problem, which is no smooth animations. When you keep scrolling up, the .stop() gets executed, and then the scroll-up animation continues, creating a weird animation effect.
$(document).ready(function() {
$(window).load(function() {
var $menu = $('.mobile-menu');
var previousTop = $menu.offset().top;
$(document).scroll(function() {
// Determine scroll position
var top = $(this).scrollTop();
// Check if user is scrolling up
if (top < previousTop) {
// .stop() prevents animation queue build-up
$menu.animate({
top: 0
}, 200);
}
else {
// .stop() prevents animation queue build-up
$menu.animate({
top: -$menu.outerHeight()
}, 200);
}
previousTop = top;
});
});
});
Fiddle: http://jsfiddle.net/8wwtLda3/
I know I can fix this using CSS transitions, but the script has to be reusable, and editing the CSS files isn't always an options.
Any tips on how to get smooth jQuery animations, without a queue building up?
SOLUTION: Thanks to Fonzy for telling me about .queue() I was able to fix this.
http://jsfiddle.net/8wwtLda3/1/
Related
I'm using the plugin Smooth Scrollbar (here).
I have an animation on my fixed header (outside the smooth scrollbar container) and triggered when user starts scrolling the smooth scrollbar container. As mentioned in the documentation (here), it's not possible that scrollbars fire scroll events. So we have to use:
scrollbar.addListener((status) => {
...
});
This is the code to animate my fixed header:
$(window).scroll(function() {
if ($(this).scrollTop() > 50){
$('.site_header').removeClass('is--large').addClass('is--small');
}
else{
$('.site_header').removeClass('is--small').addClass('is--large');
}
});
I can't figure it out how to integrate it with Smooth Scrollbar plugin. I tried various solutions to use addListener but I can't make it work.
Any help would be much appreciated!
I know it's been a while but:
const scroller = document.querySelector('.scrollable');
const bodyScrollBar = Scrollbar.init(scroller, { damping: 0.1, delegateTo: window, alwaysShowTracks: false });
bodyScrollBar.addListener( () => {
if (bodyScrollBar.scrollTop > 50){
$('.site_header').removeClass('is--large').addClass('is--small');
}
else{
$('.site_header').removeClass('is--small').addClass('is--large');
}
}
)
where .scroller is my scrolling container. Whenever you call the variable bodyScroller in the console you can see all options set and what value you can retrieve at any time. In this instance, by calling .scrollTop (NOT a function) you can retrieve its offset top value at any time.
this is my simple scroll function.
When user scrolls a certain distance from the bottom of the page, a registration box appears via animation:
$(window).scroll(function(){
if($docHeight - $top < 500 && document.cookie.indexOf("flag") < 0) {
$('.register').stop().animate({
'bottom': -1,
});
return false;
}
});
My problem is that the .stop() function before .animate() triggers every time the user scrolls; and so during animation it is constantly stopping as the user scrolls causing a 'juddering' effect (of course, no juddering if the user doesn't scroll).
I have thought about setting flags during animation and not running the animation to avoid this, but I can't figure it out.
I believe the function .once() could be used well here?
Thanks
I'm working on a slideshow area. I want to make it so scrolling horizontally will trigger an animation which moves the scrollable area to the next "slide."
Everything is working, but only if I scroll just a tiny bit. If I scroll more, the GSAP scrolling animation fails silently.
There are two ways that would make sense for this to be solved which I can think of:
1 > The first would be cancelling the scroll behavior, something like this:
$viewing_area.scroll( function(event) {
if(animationIsInProgress) {
event.preventDefault();
}
}
But this way is likely to stop GSAP scrolling as well. There is no way to distinguish if the scrolling is due to GSAP or the user that I know of.
2 > The second way would be to have GSAP force it's scrolling over anything the user is doing:
TweenLite.to($viewing_area, time, {
scrollTo: { x: slide_stops[nextTarget] },
ease: Power4.easeInOut,
onComplete: function() {
console.log('scrolling completed');
animationIsInProgress = false;
}
//Some option for forcing the behavior over user scrolling
});
Are either of these things achievable, or is scrolling by it's nature, unstoppable?
It ends up, GSAP scroll to plugin has a setting for this:
http://greensock.com/docs/#/HTML5/GSAP/Plugins/ScrollToPlugin/
It is called autokill, and if it is set to false, user scrolling will not interrupt the tween.
TweenLite.to(myDiv, 2, {scrollTo:{y:400, autoKill:false}, ease:Power2.easeOut});
vol7ron showed me how to achieve an effect where an element fades in on scroll down, and fades out on scroll up here: Why does "($(this).css('opacity')==.3)" not work?
jsfiddle: http://jsfiddle.net/b7qnrsrz/16/
$(window).on("load", function () {
function fade() {
$('.fade').each(function () {
/* Check the location of each desired element */
var objectBottom = $(this).offset().top + $(this).outerHeight();
var windowBottom = $(window).scrollTop() + $(window).innerHeight();
/* If the object is completely visible in the window, fade it in */
if (objectBottom < windowBottom) { //object comes into view (scrolling down)
if ($(this).css('opacity') != 1) {
$(this).stop(true,false).fadeTo(500, 1);
}
} else { //object goes out of view (scrolling up)
if ($(this).css('opacity') == 1) {
$(this).stop(true,false).fadeTo(500, .3);
}
}
});
}
fade(); //Fade in completely visible elements during page-load
$(window).scroll(function () {
fade();
}); //Fade in elements during scroll
});
This works almost perfectly. As is, the boxes wait to fade until I've stopped scrolling. So if I smoothly scroll past three of them, rather than fading one-by-one as I scroll past each one, they all wait to fade in until after I stop scrolling. How can I remedy this so that fade triggers even while scrolling, not waiting until after stopping?
That's because there is a bug in the script.
Every time you scroll it executes the fade function. Because the animation is prefixed with a stop() the animation never really gets any time to run if you scroll slowly.
You can either remove the .stop() or find a way to only apply the fade-in to elements that are not already fading in.
There seems to be another bug. Sometimes items are not detected as being in the viewport and they will not fade in. I'm not sure why that happens. It might have something to do with scrolling really fast.
I'm trying to construct a nav bar that changes from height:'70px' to height:'50px' when the page is scrolled away from the top, and then changes back to height:'70px' whenever the page is scrolled back to the top.
To achieve this I've tried this code:
// JavaScript Document
$(document).ready(function() {
$(window).scroll(function () {
var scroll_top = $(this).scrollTop();
if (scroll_top > 0){
$('nav').animate({
height:'50px'
});
}else{
$('nav').animate({
height:'70px'
});
}
});
});
What happens with this code is that the page loads correctly, and the first time I scroll down the height animates fine. However, whenever I scroll back to top it either won't change back to height:'70px', or (and this last part happens a lot when I try to animate additional values such as width or opacity) the entire nav bar looks to be flickering as if it were caught in a loop.
I spoke to a programmer yesterday who said it sounded like the page was re-firing .animate any time the pixel value of the nav bar changed while animating, creating an infinite loop. He suggested I implement a return false; condition to remedy this, but I'm unsure how exactly to implement it. Any help?
Suggestions on how do achieve this same effect in a different, more effective manner would also be appreciated.
Make it a lot simpler:
Have some CSS:
nav {
height:50px;
transition:height 0.4s ease;
}
nav.scrolledFromTop {height:70px}
Now your jQuery:
$(window).scroll(function() {
$("nav")[this.scrollTop > 0 ? "addClass" : "removeClass"]("scrolledFromTop");
});
Done! That is the magic of CSS3 ;)