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.
Related
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 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/
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).
im making a navigation bar that slides out from the left side of my website when you hover over the leftovers of the nav-bar. The catch is that when the animation runs and you hover your mouse back on the content section, it doesnt get registered and the nav-bar stays extended until you hover back and forth on the nav-bar once more. Does anyone know a solution for this?
var hover = 0; //navbar holder
var leave = 0; //true if mouse left navbar
$("#navhover").hover(function(){
hoverfunc(0,0,1,0,"+",1);
$("#navhover").removeClass("navhovershow");
$("#navhover").addClass("navhoverhide");
},function(){});
$("#content").hover(function(){
hoverfunc(1,0,0,1500,"-",0);
$("#navhover").removeClass("navhoverhide");
$("#navhover").addClass("navhovershow");
},function(){});
function debugging(zeroone){
$("#debugging").text(zeroone);
}
function hoverfunc(onleave,onhover,setleave,delay,addsub,numbah){
if (leave == onleave && hover == onhover) {
leave = setleave;
hover = 1;
debugging(numbah);
setTimeout(function() {
$("#navbar").animate({"left": addsub + "=170px"}, "300").queue(function(){
hover = 0;
$(this).dequeue();
});
},delay);
}
};
Here you can see the code in action: http://jsfiddle.net/cV3LU/
Any improvements on the code itself are also highly appreciated
This seems to do what you want:
function show() {
$("#navbar").stop().animate({"left": "0px"}, "300");
$("#navhover").removeClass("navhovershow");
$("#navhover").addClass("navhoverhide");
}
function hide() {
$("#navbar").stop().animate({"left": "-170px"}, "300");
$("#navhover").removeClass("navhoverhide");
$("#navhover").addClass("navhovershow");
}
$("#navhover").hover(show, hide);
The key is the call to stop(), which aborts whatever current animation is running if the mouse leaves the navigation bar while the animation is running.
You can see it working at this fiddle: http://jsfiddle.net/cV3LU/2/
Add a promise.
$("#navbar").animate({"left": addsub + "=170px"}, "300").queue(function(){
hover = 0;
$(this).dequeue();
});
$("#navbar").promise().done(function() {
// check mouse location. collapse if out.
});
The promise will run as soon as the animation finished. Useful.
-- edited --
Easiest way to check mouse location is to add a mouse move function. Everytime the mouse moves you log the location into window.x and window.y
$(document).mousemove(function(e) {
window.x = e.pageX;
window.y = e.pageY;
});
Then, your current mouse location is always window.x. Check in promise.
$("#navbar").promise().done(function() {
if (window.x > 170) {
alert("out");
} else {
alert("in");
}
});
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/