Jquery scroll with scrollTop Position is really slow to scroll - javascript

I have infinity scroll and each time the top scroll reach to certain part of the div, it loads a new content until its over. But each time it loads, it get very slow. It happens when I put some code inside of .each function, and that my scroll becomes really slow, which is annoying. I don't know how to fix it
function scrollAnimationFrame(ticking, windowHeight, tabSelected){
if (!ticking) {
window.requestAnimationFrame(function() {
scrollEvent(tabSelected, windowHeight);
ticking = false;
});
}
ticking = true;
}
function scrollEvent(tabSelected, windowHeight) {
var activeTab = document.getElementsByName(tabSelected)[0]
var divResults = activeTab.getElementsByClassName('div-content');
var scrollY = window.scrollY || document.documentElement.scrollTop;
var pos = $(window).scrollTop();
var scrollY = window.scrollY || document.documentElement.scrollTop;
$(divResults).each(function(i, el){
var posOutsideDiv = $(el).offset().top + $(el).outerHeight();
var inside = (scrollY >= $(el).offset().top && scrollY <= posOutsideDiv - 150)
if(inside){
toggleThead(el, "visible");
} else if(scrollY >= $(el).offset().top && scrollY <= posOutsideDiv + $(document).height()){
toggleThead(el, "hidden");
} else {
toggleThead(el, "visible");
}
});
}

Okay, I thought it was javascript that the scroll is getting slower each time appending a new content. So I checked at AngularJs and I was reusing the directive template. So basically create two directives for each template and voilá(Hated doing this). No more slow scroll.

Related

getBoundingClientRect() showing different values on load vs scroll

I'm working on a site for a client and trying to implement custom parallax functionality. I have used the following code -
var inView = function(element) {
// get window height
var windowHeight = window.innerHeight;
// Get Element Height
var elementHeight = element.clientHeight;
// get number of pixels that the document is scrolled
var scrollY = window.scrollY || window.pageYOffset;
// get current scroll position (distance from the top of the page to the bottom of the current viewport)
var scrollPosition = scrollY + windowHeight;
var elementPosition = element.getBoundingClientRect().top + scrollY;
var elementScrolled = elementPosition + element.clientHeight + windowHeight
// is scroll position greater than element position? (is element in view?)
if (scrollPosition > elementPosition && scrollPosition < elementScrolled) {
return true;
}
return false;
}
// Get all the elements to be parallaxed
const parallaxElements = {
element: document.querySelectorAll('#header-image img'),
ratio: 0.25
}
// The parallax function
const parallax = elements => {
let items = [...elements.element],
itemRatio = elements.ratio
if ('undefined' !== items && items.length > 0 ) {
items.forEach( item => {
if ( inView(item) == true ) {
item.style.transform = 'translate3d(0, ' + (itemRatio * (window.innerHeight - item.getBoundingClientRect().top)) + 'px ,0)'
}
})
}
}
//If element is in viewport, set its position
parallax(parallaxElements)
//Call the function on scroll
window.onscroll = () => {
parallax(parallaxElements)
}
It's working ok except that when the page is loaded initially and the user starts scrolling, the position of element (#header-image img in this case) changes abruptly. I did some digging and noticed that the value of getBoundingClientRect().top is causing the issue.
When the page is loaded, it has some value, and as soon as the user starts scrolling, it abruptly changes to another value.
I am not able to figure out why this is happening. getBoundingClientRect().top is supposed to get the value of element from top of viewport, right?
Any help is greatly appreciated. Thanks!
Pls check the screenshot of inspect element here -
https://i.stack.imgur.com/RYDvK.jpg

Recalculate Offset Value on window resize

I am creating a continuous looping page of images. Looping in both directions from div #loop-end to #loop-start with jquery scroll and offset top.
https://codepen.io/akmalmo/pen/eYgoQKd
var element_position = $('#loop-start').offset().top;
$(document).on('scroll', function() {
var y_scroll_pos = window.pageYOffset;
var scroll_pos_test = element_position;
if(y_scroll_pos > scroll_pos_test + 2) {
var loopend = $('#loop-end').offset().top;
var loopstart = $('#loop-start').offset().top;
$(document).scroll(function() {
if ( $(document).scrollTop() >= loopend + 1 ) {
$(document).scrollTop($('#loop-start').offset().top)
}
else if ( $(document).scrollTop() <= loopstart - 1 ) {
$(document).scrollTop($('#loop-end').offset().top)
}
});
}
});
The problem is that this function breaks on window resize and I am wondering if there is a simple way to recalculate the offset value? Or preferably having it calculate the offset in a more responsive fashion?
You can use the jQuery resize event to recalculate the looping variables each time the window is resized.
$(window).resize(function() {
// your function
});

Execute code after scrolling a certain amount of pixels from a certain point (up or down)

I'm currently making an overlay that covers a sticky top bar when the user has scrolled beyond a certain point (down) and disappears when scrolling back up. However, I'd like to be able to scroll for at least 50px before the code is executed (something like a gap before the overlay is triggered).
$(function() {
var prevScroll = $(document).scrollTop(); //initial position
$(window).scroll(function() {
var newScroll = $(document).scrollTop(); //position from top after scrolling
if(newScroll > prevScroll) { // checks if the user has scrolled up or down
var fromNew = $(document).scrollTop(); // holds value to compare with the position + gap amount
if (fromNew > newScroll + 50) { //checks to see if scrolled for 50px
$("#stick-start").fadeIn("fast");
prevScroll = newScroll + 50; //initial position + scrolled amount
};
} else {
var fromNew = $(document).scrollTop();
if (fromNew > newScroll - 50) {
if ($("#stick-start").hasClass("is-stuck")) {
$("#stick-start").fadeOut("fast");
prevScroll = newScroll - 50;
};
};
};
});
});
The condition that checks whether you're scrolling up or down works. But as it is now, the overlay just keeps fading in and out repeatedly. How do I make it so that you have to scroll at least 50px before anything happens ?
I think this should get you where you're going.
var $document = $(document);
$(window).scroll(function() {
if ($document.scrollTop() >= 50) {
$("#stick-start").fadeIn("fast");
} else {
$("#stick-start").fadeOut("fast");
}
});
EDIT: had an error, should be good now.
$(window).scroll(function() {
if ($(this).scrollTop() >= 50) {
$("#stick-start").fadeIn();
} else {
$("#stick-start").fadeOut();
}
});

Pure Javascript, How to detect if scrollTop will scroll to the bottom of the page?

I have a function which basically runs when an arrow with the class 'downArrow' is click. The function will find the parent of that arrow then find the next sibling with a class of 'scrollPoint' and then scroll to that area. Everything I just described works fine for me the issue I am having is if the bottom of the document hits the bottom of my viewport before the top of the element I am scrolling to hits the top of the viewport it just glitches out and scrolls back to the very top of the document. So I think What I need to do is detect if this scenario is going to happen and then set a max scroll value so the scroll functions doesnt try to scroll passed the bottom of the document.
How would I detect if the bottom of the document will be visible on the viewport and prevent from scrolling that far?
I will provide my code below in hopes that it will help, if you have any questions or need more clarification of what I am asking for just let me know. Thanks
This is my component although for what i am asking only the scrollTo function is really relevant
exports.init = init;
function init (options){
var downArrows = document.querySelectorAll(options.selector);
downArrows.forEach(triggerScrollHandler);
}
function scrollTo(element, to, duration) {
if (duration < 0) return;
var difference = to - element.scrollTop;
var perTick = difference / duration * 10;
setTimeout(function() {
element.scrollTop = element.scrollTop + perTick;
if (element.scrollTop === to) return;
scrollTo(element, to, duration - 10);
}, 10);
}
function scrollHandler (e) {
e.preventDefault();
var el = this,
scrollPoint = findSibling(el),
offsetVal = scrollPoint.getBoundingClientRect(),
windowOffset = window.pageYOffset;
offsetVal = offsetVal.top + windowOffset - 1;
scrollTo(document.body, offsetVal, 600);
}
function findParent(el) {
while (el && el.parentNode) {
el = el.parentNode;
if (el.tagName) {
return el;
}
}
return null;
}
function findSibling (el) {
var parent = findParent(el),
siblings = document.querySelectorAll('.scrollPoint'),
scrollTo;
siblings.forEach(function (currentSib, i) {
if(scrollTo == 'found'){
scrollTo = currentSib;
}
if(currentSib == parent){
scrollTo = 'found'
}
});
return scrollTo;
}
function triggerScrollHandler (el) {
el.addEventListener('click', scrollHandler);
}
And this is where I call in my app.js
var scrollHandler = require('./components/scrollHandler.js');
(function(){
scrollHandler.init({
selector: '.downArrow'
});
}())
Put this in your scroll listener:
if (document.body.scrollHeight <= document.body.scrollTop + document.body.clientHeight ){
console.log('scrolled to bottom');
}
Simple, pure JS solution :)

fadein only if I'm scrolling down

I'm using this snippet to make an element fade out if scrolltop is > 750 and fade in when it's < 750. It works fine but I'd like it to remain not visible when scrolling back up (after it faded out) until user reaches the top of the page.
So, this is what's currently happening:
element is visible by default, user scrolls 750 and it fades out. User reaches end of the page, scrolls back up and when reaches 750 the element fades back in.
var $window = $(window);
var $freccia = $('#freccia1');
function showHideFreccia() {
var availableScroll = $(document).height() - $window.height(),
scrollTop = $window.scrollTop();
if( scrollTop < 750 || scrollTop == availableScroll) {
$freccia.fadeIn("slow", function() {
});
} else {
$freccia.fadeOut("slow", function() {
});
}
}
showHideFreccia();
$window.scroll(showHideFreccia);
What should be changed is:
element is visible by default, user scrolls 750 and it fades out. User reaches end of the page, scrolls back up and when reaches top of the page the element fades back in.
I tried with this but it's not working (doesn't fade in/out anymore):
var $window = $(window);
var $freccia = $('#freccia1');
function showHideFreccia() {
var availableScroll = $(document).height() - $window.height(),
scrollTop = $window.scrollTop();
if ( scrollTop > 750 || scrollTop == availableScroll) {
$freccia.fadeout("slow", function() {
});
}
if ( scrollTop < 1 || scrollTop == availableScroll) {
$freccia.fadein("slow", function() {
});
}
}
showHideFreccia();
$window.scroll(showHideFreccia);
Your second code snippet works fine, you've just used fadein and fadeout instead of fadeIn and fadeOut, a common mistake!
This code is working fine for me:
JSFiddle
var $window = $(window);
var $freccia = $('#freccia1');
function showHideFreccia() {
var availableScroll = $(document).height() - $window.height(),
scrollTop = $window.scrollTop();
if ( scrollTop > 750 || scrollTop == availableScroll) {
$freccia.fadeOut("slow", function() {
});
}
if ( scrollTop < 1 || scrollTop == availableScroll) {
$freccia.fadeIn("slow", function() {
});
}
}
showHideFreccia();
$window.scroll(showHideFreccia);
EDIT:
Unsure if this is what you want to happen or not, but this current code will show the element again when you reach the end of the page. You can fix this just by removing the || scrollTop == availableScroll from your second if statement (if it's not needed at all, it can be removed from the first also).
You can use this script, to apply in your scroll top:
var detectScroll = function (_event) {
var event = window.event || _event; // old IE support
var direction = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail)));
return direction;
};
function showHideFreccia(e) {
var dir = detectScroll(e);
//...
if ( dir == 1 || scrollTop == availableScroll) {
// your action
}
}
// and into your scroll event
$window.scroll(function(e) {
showHideFreccia(e);
});
Source
If it will return 1 it means, that you scroll up then execute your fadein action. -1 me means scroll to bottom

Categories