I have a small problem with my looping scroll. It works pretty well on larger displays, but on handheld devices it glitches quite a lot. I'm not sure where I'm doing something wrong or where I should adjust the code to work on mobile as well.
Link to site: https://studio-6-9ede0f.webflow.io/
Here's what I got so far:
var origDivHeight = document.querySelector(".infinite").offsetHeight;
var clone=$(".infinite").contents().clone();
clone.appendTo(".infinite");
clone.prependTo(".infinite");
$(document).scroll(function(){
var scrollWindowPos = $(document).scrollTop();
if(scrollWindowPos >= origDivHeight ) {
$(document).scrollTop(0);
}
if(scrollWindowPos <= 0 ) {
$(document).scrollTop(origDivHeight);
}
});
window.scrollBy(0, 1);
window.scrollBy(0, -1);
Got it to work based on this codepen: https://codepen.io/vincentorback/pen/zxRyzj
Sharing it here as well if somebody finds it useful:
<style>
html,
body {
height: 100%;
overflow: hidden;
}
.infinite {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
.clone {
height: 50vw;
}
</style>
<script>
var doc = window.document,
context = doc.querySelector('.infinite'),
clones = context.querySelectorAll('.clone'),
disableScroll = false,
scrollHeight = 0,
scrollPos = 0,
clonesHeight = 0,
i = 0;
function getScrollPos () {
return (context.pageYOffset || context.scrollTop) - (context.clientTop || 0);
}
function setScrollPos (pos) {
context.scrollTop = pos;
}
function getClonesHeight () {
clonesHeight = 0;
for (i = 0; i < clones.length; i += 1) {
clonesHeight = clonesHeight + clones[i].offsetHeight;
}
return clonesHeight;
}
function reCalc () {
scrollPos = getScrollPos();
scrollHeight = context.scrollHeight;
clonesHeight = getClonesHeight();
if (scrollPos <= 0) {
setScrollPos(1); // Scroll 1 pixel to allow upwards scrolling
}
}
function scrollUpdate () {
if (!disableScroll) {
scrollPos = getScrollPos();
if (clonesHeight + scrollPos >= scrollHeight) {
// Scroll to the top when you’ve reached the bottom
setScrollPos(1); // Scroll down 1 pixel to allow upwards scrolling
disableScroll = true;
} else if (scrollPos <= 0) {
// Scroll to the bottom when you reach the top
setScrollPos(scrollHeight - clonesHeight);
disableScroll = true;
}
}
if (disableScroll) {
// Disable scroll-jumping for a short time to avoid flickering
window.setTimeout(function () {
disableScroll = false;
}, 40);
}
}
function init () {
reCalc();
context.addEventListener('scroll', function () {
window.requestAnimationFrame(scrollUpdate);
}, false);
window.addEventListener('resize', function () {
window.requestAnimationFrame(reCalc);
}, false);
}
if (document.readyState !== 'loading') {
init()
} else {
doc.addEventListener('DOMContentLoaded', init, false)
}
</script>
Related
My code snippet's purpose is to reveal an animation while the scrollY is on 0 if the scrollY is above 0 it will reveal other animations, however, the code only works once.
function reveal() {
var reveals = document.querySelectorAll(".navbar");
var i = 0;
for ( i; i < reveals.length; i++) {
if (window.scrollY > 0) {
reveals[i].classList.add("active");
} else if (window.scrollY == 0) {
reveals[i].classList.add("nactive");
} else {
}
}
}
window.addEventListener("scroll", reveal);
reveal();
the function needs to be looped but I don't know how.
I am trying to create a on scroll fade animation in my website i am using reactjs for this although i didnt knew how to bring this effect so i found this jquery code to achive this effect but i want to bring this effect without jquery using plane react is it possible? here is the jquery code:
var html = $('html');
// Detections
if (!("ontouchstart" in window)) {
html.addClass("noTouch");
}
if ("ontouchstart" in window) {
html.addClass("isTouch");
}
if ("ontouchstart" in window) {
html.addClass("isTouch");
}
if (document.documentMode || /Edge/.test(navigator.userAgent)) {
if (navigator.appVersion.indexOf("Trident") === -1) {
html.addClass("isEDGE");
} else {
html.addClass("isIE isIE11");
}
}
if (navigator.appVersion.indexOf("MSIE") !== -1) {
html.addClass("isIE");
}
if (
navigator.userAgent.indexOf("Safari") != -1 &&
navigator.userAgent.indexOf("Chrome") == -1
) {
html.addClass("isSafari");
}
// On Screen
$.fn.isOnScreen = function() {
var elementTop = $(this).offset().top,
elementBottom = elementTop + $(this).outerHeight(),
viewportTop = $(window).scrollTop(),
viewportBottom = viewportTop + $(window).height();
return elementBottom > viewportTop && elementTop < viewportBottom;
};
function detection() {
for (var i = 0; i < items.length; i++) {
var el = $(items[i]);
if (el.isOnScreen()) {
el.addClass("in-view");
} else {
el.removeClass("in-view");
}
}
}
var items = document.querySelectorAll(
"*[data-animate-in], *[data-detect-viewport]"
),
waiting = false,
w = $(window);
w.on("resize scroll", function() {
if (waiting) {
return;
}
waiting = true;
detection();
setTimeout(function() {
waiting = false;
}, 100);
});
$(document).ready(function() {
setTimeout(function() {
detection();
}, 500);
for (var i = 0; i < items.length; i++) {
var d = 0,
el = $(items[i]);
if (items[i].getAttribute("data-animate-in-delay")) {
d = items[i].getAttribute("data-animate-in-delay") / 1000 + "s";
} else {
d = 0;
}
el.css("transition-delay", d);
}
});
});
is there any way that i can bring this effect from react only or do i have to use :
import $ from jquery
thanks in advance
So I have write a script for my portfolio website to scroll to section by index. It works on every tested browser and smartphone but on a mac device it does not work probably instead to scroll to the next sections it is going automatically to the second next section.
Hopefully someone can help me.
var anchorPoints = [];
var anchorLocation = [];
var anchorIndex = 0;
var waiting = false;
var canScroll = true;
var offset = 0
window.onload = function () {
anchorPoints = document.getElementsByClassName("js-anchor");
for (i = 0; i < anchorPoints.length; i++) {
getLocation = anchorPoints[i].getBoundingClientRect();
getLocation = getLocation.top - offset;
anchorLocation.push(parseInt(getLocation));
}
}
$(document).on('mousewheel DOMMouseScroll', function (e) {
if (detectMobile() == true) {
return;
}
if ((waiting || canScroll == false)) {
return;
}
e.preventDefault();//prevent the default mousewheel scrolling
var active = $('section.active');
var delta = e.originalEvent.detail < 0 || e.originalEvent.wheelDelta > 0 ? 1 : -1;
waiting = true;
if (delta < 0) {
anchorIndex += 1;
if (anchorIndex > (anchorPoints.length - 1)) {
anchorIndex = 0;
}
scrollTo({
top: anchorLocation[anchorIndex],
left: 0,
behavior: 'smooth'
});
console.log(anchorIndex);
console.log('scrolling down');
} else {
anchorIndex -= 1;
if (anchorIndex < 0) {
anchorIndex = anchorPoints.length - 1;
}
scrollTo({
top: anchorLocation[anchorIndex],
left: 0,
behavior: 'smooth'
});
console.log(anchorIndex);
console.log('scrolling up');
}
setTimeout(function () {
waiting = false;
}, 1000);
});
I had onepageNav script to scrollTo pages. Pages it's not full height of window than i had problem with addition mousewhell.
I had code:
$('body').mousewheel(function(event, delta) {
if (flag) { return false; }
$current = $('section.current');
if (delta > 0) {
$prev = $current.prev();
if ($prev.length) {
flag = true;
$('body').scrollTo($prev, 1000, {
onAfter : function(){
flag = false;
}
});
$current.removeClass('current');
$prev.addClass('current');
}
} else {
$next = $current.next();
if ($next.length) {
flag = true;
$('body').scrollTo($next, 1000, {
onAfter : function(){
flag = false;
}
});
$current.removeClass('current');
$next.addClass('current');
}
}
event.preventDefault();
});
It's script for mousewheel. It's work but not exacly what i want.
If i had section #2 bigger than window than it's go automaticaly after scroll to next section.
I i had section #3 last, bigget than windows and i scroll down than scrolling stop working.
Someone had idea how to resolve that?
If I understand you correctly you can use the following code:
HTML:
<section id='s1'></section>
<section id='s2'></section>
<section id='s3'></section>
<section id='s4'></section>
JS:
function elementInViewport2(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while(el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top < (window.pageYOffset + window.innerHeight) &&
left < (window.pageXOffset + window.innerWidth) &&
(top + height) > window.pageYOffset &&
(left + width) > window.pageXOffset
);
};
var current = $('section').first();
current.addClass('current');
var flag;
$(window).scroll(function(event, delta) {
if (flag) { return false; }
var $body = $('body'),
$window = $(window),
newScroll = $body.scrollTop();
if (!elementInViewport2(current[0])) {
current.removeClass('current');
current[0] = null;
}
var newSection = $('section:not(.current)').filter(function(i, el) {
return elementInViewport2(el);
}).first();
if (newSection[0] && current[0] != newSection[0]) {
current.removeClass('current');
current = newSection;
newSection.addClass('current');
flag = true;
$body.animate({scrollTop: newSection.offset().top}, function() {
flag = false;
});
event.preventDefault();
}
});
Demo
I have a script that I want to execute only when a user reaches a position X (under my Nav bar) and to stop only when the user reaches this position X again (under my Nav bar).
How to achieve this effect?
EDIT:
How can I implement this code:
var reachedFromTop = false;
var reachedFromBottom = false;
$(window).scroll(function() {
//After scrolling 100px from the top...
if ($(window).scrollTop() > 100 ) {
if (!reachedFromTop) something();
reachedFromTop = true;
} else if (reachedFromTop && otherCondition) {
if (!reachedFromBottom) somethingElse();
reachedFromBottom = true;
}
});
in my existing script:
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('.main-navigation').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
if(Math.abs(lastScrollTop - st) <= delta)
return;
if (st > lastScrollTop && st > navbarHeight){
$('.main-navigation').removeClass('nav-down').addClass('nav-up');
} else {
if(st + $(window).height() < $(document).height()) {
$('.main-navigation').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
you should be able to do something like this.
var reachedFromTop = false;
var reachedFromBottom = false;
$(window).scroll(function() {
//After scrolling 100px from the top...
if ($(window).scrollTop() > 100 ) {
if (!reachedFromTop) something();
reachedFromTop = true;
} else if (reachedFromTop && otherCondition) {
if (!reachedFromBottom) somethingElse();
reachedFromBottom = true;
}
});
and you need to include jquery as your dependency