JS scrollTo next Section onscroll - javascript

i'd like to limit scrolling on my webpage to divs/sections whatever.
Like limiting the scroll step to the screen-height.
If a user scrolls whether it is with a mouse-wheel or a mac 2-finger-scroll.
He should scroll automatically to the next section or the previous one.
Example pages: Jenny Example FLPNY Example
I have already found a function here, to limit listening to the scroll event (debounce). I just can't figure out how no to get a random scroll behaviour.
function debounce(func, interval) {
var lastCall = -1;
return function () {
clearTimeout(lastCall);
var args = arguments;
lastCall = setTimeout(function () {
func.apply(this, args);
}, interval);
};
}
$(window).on('wheel', debounce(function (e) {
currentScrollPosition = document.documentElement.scrollTop || document.body.scrollTop;
var delta = e.originalEvent.deltaY;
if (delta > 0) {
console.log("down");
$("html, body").animate({
scrollTop: nextSection
}, 500);
}
else {
console.log("up");
// this will search within the section
$("html, body").animate({
scrollTop: prevSection
}, 500);
}

Not quite sure what you mean by:
I just can't figure out how no to get a random scroll behaviour.
But the site you link is making use of fullPage.js.

Related

JS Scroll window while mouseover

I would like to scroll up or down the window while the mouse is over a specific element.
What I have so far basically works but it's not "smooth". It starts and stops on and on, not looking nice. Do you have any idea how to make a more constant smooth scrolling?
This is my code:
doScroll = 0;
$(".helperDown").mouseenter(function() {
scrollHandler = setInterval( function() {
console.log('scrolling down...');
if(doScroll == 0) {
doScroll = 1;
$("html, body").animate({scrollTop: fromTop+50}, 200, 'linear', function() {
doScroll = 0;
});
}
}, 200);
});
$(".helperDown").mouseleave(function() {
clearInterval(scrollHandler);
});
.helperDown is the area where the mouse has to be in to start scrolling. fromTop is always recalculated after a scroll event.
You can not start a series of animation and expect a smooth scrolling. What you need is to start one animation only by pre-calculating the distance this animation will cover. Also, jQuery has a nice wrapper for mouseenter and mouseleave -combined. It's the hover() function with two functions as its parameter. The following code block will solve your issue.
Also, this plnkr has both the up and down scroll feature:
https://plnkr.co/edit/WoneJ8?p=preview
$(function () {
// change this value as per your need
var distancePerSec = 1000;
$(".helperDown").hover(function () {
var h = $("body").height();
var targetScrollTop = h - $(window).height();
var distanceToTravel = targetScrollTop - $(window).scrollTop();
var animationDuration = (distanceToTravel / distancePerSec) * 1000;
$("html, body").animate({
scrollTop: targetScrollTop
}, animationDuration, 'linear');
}, function () {
// stop the animation
$("html, body").stop();
});
})

Javascript scroll to element on scroll

I searched very long but haven't found a soulution yet.
I want to scroll to the next element on scroll.
$(window).load(function(){
var scroll = false;
$(function() {
//Create an Array
var sites = $('.site');
var position = 0; //Start Position
var next = $('#next');
var lastScrollTop = 0;
$(window).scroll(function(event){
if(scroll == false){
scroll = true;
$(document).off('scroll');
var st = $(this).scrollTop();
if (st > lastScrollTop){
if (position !== sites.length - 1) {
scrollToPosition(sites[position += 1]),5000;
}
} else {
if (position !== 0) {
scrollToPosition(sites[position -= 1]),5000;
}
}
lastScrollTop = st;
}
});
})
function scrollToPosition(element) {
if (element !== undefined) {
scrollToElement($(element).attr('id'));
}
}
function scrollToElement(selector, time, verticalOffset) {
time = typeof(time) != 'undefined' ? time : 500;
verticalOffset = typeof(verticalOffset) != 'undefined' ? verticalOffset : 0;
selector = "#" + selector;
var element = $(selector);
offset = element.offset();
offsetTop = offset.top + verticalOffset;
$('html, body').animate({
scrollTop: offsetTop
}, time);
scroll = false;
}
});
the html has many of these with different ids
<div id="test" style="width:100%; height:100vh;" class="site">
</div>
So the containers are fullscreen hight. and when the user scrolls a bit he should get to the next container.
At the moment it scrolls till the end and or more.
It would help if you could create an example in jsFiddle or CodePen, but the first thing I would do is stop any current jQuery animations before launching new ones:
$('html, body').stop().animate({
scrollTop: offsetTop
}, time);
You should keep in mind that scroll handler is executed many times when user is scrolling.
Also, unrelated - your scrollToPosition calls have brackets at the wrong place and should probably be like this:
scrollToPosition(sites[position += 1], 5000);
Edit:
Another thing that might cause problems - you should unset the 'scroll' flag/variable only when the animation has finished, something like this:
$('html, body').stop().animate({
scrollTop: offsetTop
}, time, function () {
scroll = false;
});

How to scroll once in $(window).scroll() have another scroll command

I have a vertical photo viewer
and i need a scroll effect is once a page height when mouse wheel down.
so i have following code
$(document).ready(function() {
$(window).scroll(function () {
var H = $(window).height();
var st = $(this).scrollTop();
$("html, body").animate({ scrollTop: H + st }, 500, function () {
console.log("finish scroll");
});
});
});
But when i scroll once, it will repeat again and again until to the bottom.
How can i solve this problem?
Thanks in advance.
I used a counter and a timer so that the counter waits half a second after the scroll has finished..
http://jsfiddle.net/beardedSi/p45rH/1/
$(document).ready(function () {
var H = $(window).height(),
go = true;
console.log(H);
//just for visual, set the height of boxes to be same as window height
//to check it is all working
$('.box').css('height', H + "px");
function scroller() {
$("html, body").animate({
scrollTop: '+=' + H
}, 400, function () {
console.log("finished");
setTimeout(function () {
go = true;
}, 400);
});
}
$(document).on('scroll', function (e) {
e.preventDefault();
if (go) {
go = false;
scroller();
}
});
});
The problem is the animation make a scroll event too. so you have a scrolling loop.
To resolve that, you can add a flag.
It's not the best way to solve your problem but you can do this => http://jsbin.com/qagayopu/2/edit

Firing an animation when aligned

I am creating a splitscrolling website and it's working great. But i have one problem, when the user stops scrolling it fires a function called alignWhenIdle and what this does is align the columns so they become "one".
Now that is working nicely but i can't seem to target a specific part of the column that aligns. let's say when the number 2 column aligns ( see image ) i want to be able to fire an animation. I tried using a callback but that fires a function every time the columns are aligned.
This is my JS:
(function ($) {
var top = 0;
var contentHeight, contents, totalHeight;
var locked = false;
var timeout;
var align = function () {
var pos = (top + $(window).scrollTop());
var snapUp = 0 - (pos % contentHeight) < (contentHeight / 2);
var multiplier = snapUp
? Math.ceil(pos / contentHeight)
: Math.floor(pos / contentHeight);
var newTop = contentHeight * multiplier;
$('html, body').animate({ scrollTop: newTop + totalHeight }, 200);
locked = false;
};
var reset = function () {
contentHeight = $('.right').height();
contents = $('.right > .content').length;
totalHeight = contentHeight * (contents - 1);
top = (0 - totalHeight);
};
var scrollRight = function () {
$('.right').css('top', (top + $(window).scrollTop()) + 'px');
};
var alignWhenIdle = function (delay) {
clearTimeout(timeout);
timeout = setTimeout(align, delay);
};
$(document).on('ready', function () {
reset();
scrollRight();
});
$(window).on('scroll', function () {
locked = true;
scrollRight();
});
$(window).on('mouseup', function (e) {
if (locked) {
align();
}
});
$(window).resize(function () {
locked = true;
reset();
scrollRight();
alignWhenIdle(300);
});
$(window).on('mousewheel', function (e) {
alignWhenIdle(300);
});
$(window).on("keyup", function (e) {
alignWhenIdle(300);
});
})(jQuery);
http://jsfiddle.net/ev3B8/
Any help is much appreciated,
Cheers
See http://jsfiddle.net/5T9Y8/
Scroll till the column 2 and see result...
In the method align I've added a callback:
$('html, body').animate({ scrollTop: newTop + totalHeight }, 200, function(){
$(".animate").animate({ marginLeft: "200px" },300);
});
Works well, did you need exactly that?
EDIT
You should just check for some condition.
E.g. based on this solution Check if element is visible after scrolling you can build this:
$('html, body').animate({ scrollTop: newTop + totalHeight }, 200, function(){
if (isScrolledIntoView(".animate")) $(".animate").animate({ marginLeft: "200px" },300);
});
See updated solution here http://jsfiddle.net/5T9Y8/1/
This is only one way, I'm really sure there is a way to do it even better. E.g. you can calculate the current elements which are shown and then just find the things only inside of them.
I tried using a callback but that fires a function every time the columns are aligned.
Use one method for functioning only once instead of on.

Delay mousewheel function

I'm using the mousewheel and waypoints plugin to scroll sections of my page; The problem I am having is when I scroll using the apple mighty mouse the scrolling is too sensitive and the function gets triggered more then once when the animation is complete. I tried to set a timeout function and variable to check if the animation is complete but neither of these worked.
I would like to replicate an effect similar to the one on this website.
JQUERY
$('body').mousewheel(function(event, delta, deltaX, deltaY) {
clearTimeout(interval);
console.log('test');
$('section').waypoint(function(direction){
thisID = $(this);
},{ offset: '350' });
indexPos = thisID.index('section');
if (completed == true) {
completed = false;
var interval = "";
if (delta > 0) {
interval = setTimeout(function(){
if ($(this).not(":first-child")) {
//$(this).animate(function(){
$('html, body').stop().animate({
scrollTop: thisID.prev().offset().top - 200
}, 1000, 'swing' , function() { completed = true; });
//});
}else {
$('html, body').stop().animate({
scrollTop: thisID.offset().top - 200
}, 1000, 'swing' , function() { completed = true; });
}
},400);
}
else if (delta < 0) {
interval = setTimeout(function(){
if ($(this).not(":first-child")) {
$('html, body').stop().animate({
scrollTop: thisID.next().offset().top - 200
}, 1000, 'swing' , function() { completed = true; });
}
else {
$('html, body').stop().animate({
scrollTop: thisID.offset().top - 200
}, 1000, 'swing' , function() { completed = true; });
}
},400);
}
};
return false; // prevent default
});
I don't know what this is doing: indexPos = thisID.index('section'); but before doing anything, I would check if ins't anything in progress already:
$('body').mousewheel(function(event, delta, deltaX, deltaY) {
if($('html').is(':animated') || $('body').is(':animated')) return false;
// else, do your stuff...
});
You can use underscore js http://underscorejs.org/
and do something like this:
$('body').mousewheel(_.debounce(function() {
//handle the mouse wheel event in here
}, 30)
This will wait for 30 ms from the last mousewheel event before firing the callback
This website doesn't seem to use scrolling. It merely moves to a new anchor (watch the url when scrolling) which is triggered by moving (scrolling) your mouse up or down as a trigger which feels like lagged scrolling (but in fact, you don't have any control over the direction once it moves). You can use jquery animate to do that.

Categories