I have some code that is supposed to scroll one page height every time scroll is triggered in some way. I want this to scroll only one heigh, and "pause" the trigger until the scrolling is done. However, my script does not stop, instead it will scroll all the way down instantly. Scrolling upwards seems to work better...
Here is my script:
var lastScroll = 0;
var scrollPos = 0;
var blockScroll = 0;
$(window).scroll(function() {
var scroll = $(this).scrollTop();
if(blockScroll == 0) {
blockScroll = 1;
if(scroll > lastScroll){
// Down
scrollPos++;
console.log(scrollPos+"-"+blockScroll);
$("html, body").animate({scrollTop:$(window).height()*scrollPos}, 'slow', function() {
blockScroll = 0;
});
} else {
// Up
scrollPos--;
console.log(scrollPos);
$("html, body").animate({scrollTop:$(window).height()*scrollPos}, 'slow', function() {
blockScroll = 0;
});
}
}
lastScroll = scroll;
});
blockScroll is meant to be set when a scroll event appears, and to be unset when the scrolling animation stops. As a lock. I am not shure this works the way I want it though... Can someone see something obviously wrong with this? Am I having trouble with the fact that jQuery is async?
It appears that animate is firing scroll events itself, so when it finishes, it's firing one last scroll event which restarts the process.
It seems like adding a small timeout in the callback solves the problem:
setTimeout(function () {blockScroll = 0;}, 50)
http://jsfiddle.net/qch787yq/1/
Related
I have a function that runs when the person scrolls which scrolls them directly to a section of website (in this case its "downarrow").
Function:
function scroll_to_target(){
const element = document.getElementById("downarrow");
element.scrollIntoView({
behavior: "auto"
});
}
Trigger:
var scrollPosition = $("body, html").scrollTop()
var element = document.getElementById("downarrow");
var hasScrolled = false;
window.addEventListener("scroll", function() {
if (scrollPosition == 0 && !hasScrolled) {
//element.scrollIntoView("downarrow");
hasScrolled = true;
scroll_to_target()
}
}
The code above works perfectly fine but i want it to not scroll instantly and rather scroll slowly and smoothly. So I change the behavior: "auto" to behavior: "smooth" in the function and try again but it doesnt work. However, when i put this function to a button it works smoothly but nothing happens when user scrolls.
I have a problem regarding two animations, one scrolling down and one scrolling up (when the user has scrolled back up completely).
The animations block each other - with the following source code:
jQuery(document).ready(function($) {
$(window).on("load",function() {
$(window).scroll(function(){
if($(window).offset().top == 0){
$("selector").animate({}, 500);
$("selector").animate({}, 500);
} else {
$("selector").animate({}, 500);
$("selector").animate({}, 500);
}
});
}).scroll();
});
So it happens that after the true statement block of the if directly the else part is executed again and therefore the animation is partly not executed at all or both are executed one after the other. Does anyone have an idea that the animations are executed reliably:
else animation once as soon as scrolling down was done
if-Animation as soon as scrolling up completely again
Thanks in advance!
Makes no sense to cauculate $(window).offset().top since... it does what it says. 0.
Perhaps, on "scroll" Event you want to get the $(window).scrollTop()
jQuery($ => {
const $win = $(window);
const $items = $(".item");
$win.on("scroll", () => {
$items.toggleClass("active", $win.scrollTop() == 0);
});
$win.on("load", () => {
$win.trigger("scroll");
});
});
.active {
/* your styles here */
}
I have been trying to make a function in jQuery to let a div move up faster than the rest of the page when you scroll down, and have it do the same for the opposite direction.
This works, but with a 1.5 second cooldown to avoid the spam from $(window).scroll(function(). So people have to wait 1.5 seconds when they join the site for it to work and then they have to wait 1.5 seconds to scroll up and down each time to see the effect work perfectly.
How would I go around fixing this delay? There should be no delay for good user experience. (The transition function is from a library and is not at fault here.)
var $intervalReady = false;
setInterval(function(){if($intervalReady==false){
$intervalReady = true;
}}, 1500);
$( document ).ready(function() {
var $elementBeginPos = $('#headertext').position();
$(window).scroll(function(){
var top = $(this).scrollTop();
if(top > 60 && $intervalReady==true){
$('#headertext').transition({y:'30%'});
$intervalReady = false;
}
else if(top < 60 && $intervalReady==true){
$('#headertext').transition({y:'-30%'});
$intervalReady = false;
}
});
});
Here is a working example: https://jsfiddle.net/37khp0ft/
Adjust to your needs.
In general, update the state on timer event, not on the scroll event.
JS part:
function updatePos(selector, multiplier)
{
var scrollPos = $(document).scrollTop();
$(selector).css({top: scrollPos * multiplier});
}
$(document).ready(function()
{
setInterval(updatePos, 100,'#div', -1.1 );
});
I have this code and it works exactly as I want. The menu bar sits on top and recognizes the section it is on or in. You can click the links in the yellow menu to move between the sections.
http://jsfiddle.net/spadez/2atkZ/9/
http://jsfiddle.net/spadez/2atkZ/9/embedded/result/
$(function () {
var $select = $('#select');
var $window = $(window);
var isFixed = false;
var init = $select.length ? $select.offset().top : 0;
$window.scroll(function () {
var currentScrollTop = $window.scrollTop();
if (currentScrollTop > init && isFixed === false) {
isFixed = true;
$select.css({
top: 0,
position: 'fixed'
});
$('body').css('padding-top', $select.height());
} else if (currentScrollTop <= init) {
isFixed = false;
$select.css('position', 'relative');
$('#select span').removeClass('active');
$('body').css('padding-top', 0);
}
//active state in menu
$('.section').each(function(){
var eleDistance = $(this).offset().top;
if (currentScrollTop >= eleDistance-$select.outerHeight()) {
var makeActive = $(this).attr('id');
$('#select span').removeClass('active');
$('#select span.' + makeActive).addClass('active');
}
});
});
$(".nav").click(function (e) {
var divId = $(this).data('sec');
$('body').animate({
scrollTop: $(divId).offset().top - $select.height()
}, 500);
});
});
However, the code itself gets quite laggy as soon as you start putting any content in the boxes. I wondered if there is any opportunity to optimize the code and make it run a bit smoother.
The problem you have is that you're repeatedly changing page layout properties (via the animation) and querying page layout properties (in the scroll handler), thus triggering a large number of forced layouts.
If i understand your code correctly you could get a big improvement by disabling the scroll handler during the click animation and instead triggering the effects with no checks made (set the active class on the clicked element).
I am writing a small jQuery function and I seem to be having trouble.
What I am trying to do here is when the user scrolls down the page by 90px, a div tag should animate down (from top:-50px to top:0), and vice-versa when they scroll back to the top of the page.
The problem I am having is that the animation seems to be very slow and unresponsive at times. I test in 3 different browsers and different computers but I am having no joy.
Here is my code:
// Show div
var scrollValue = "90";
// Animate functions
var showHead = function (){
$(".element").animate({top: "0"}, 250);
}
var hideHead = function (){
$(".element").animate({top: "-50px"}, 250);
}
$(window).scroll(function() {
if ($(this).scrollTop() > scrollValue) {
showHead();
} else {
hideHead();
}
});
The .element properties:
.element { positoin:fixed; top:-50px; }
Could anyone figure out why my code the hide/showHead functions are so sloppy?
Thanks,
Peter
The scroll event is triggered several times and even though it is rate-limited it keeps being a rather intensive operation. Actually, you may be queuing several animations and the fx stack may be growing very quickly.
One possibility you can try is stopping all previous animations before triggering a new one. You can do this by using .stop().
$(".element").stop().animate({top: "0"}, 250);
The .stop() function also provides some other options which you can use to tweak it even more.
Try this one :
$(window).scroll(function() {
if (window.scrollY > scrollValue) {
showHead();
} else {
hideHead();
}
});
scroll events occurred many time durring user scrolling.
You need to check if your animation is in progress before starting the animation again.
Try this :
// Show div
var scrollValue = "90";
var inProgress = false;
// Animate functions
var showHead = function () {
if(inProgress)
return false;
//Animate only if the animation is not in progress
inProgress = true;
$(".element").animate({
top: "0"
},250,function(){
inProgress = false; //Reset when animation is done
});
}
var hideHead = function () {
if(inProgress)
return false;
//Animate only if the animation is not in progress
inProgress = true;
$(".element").animate({
top: "-50px"
}, 250,function(){
inProgress = false; //Reset when animation is done
});
}
$(window).scroll(function () {
if ($(this).scrollTop() > scrollValue) {
showHead();
} else {
hideHead();
}
});
Assuming you have position:fixed (or some other sort of styling making the bar visible when necessary):
var scrollheight = 90;
var $el = $('.element');
function showHead(){
$el.stop().animate({
top: '0px'
}, 250);
}
function hideHead(){
$el.stop().animate({
top: '-50px'
}, 250);
}
$(window).scroll(function(){
if ($(window).scrollTop() > scrollheight){
showHead();
}else{
hideHead();
}
});
example: http://jsfiddle.net/L4LfL/
try using queue: false and as Alexander said use .stop()
here jsfiddle
http://jsfiddle.net/hwbPz/