Reputation: 624
I have this code for vehicle to horizontal and back to vertical scrolling, however it only works on mouse wheel scroll. I also need it to respond accordingly to mobile touch, scrollbars, page up/down, and the keyboard arrow keys. Below is my code:
(function(){
init();
var g_containerInViewport;
function init(){
setStickyContainersSize();
bindEvents();
}
function bindEvents(){
window.addEventListener("wheel", wheelHandler);
//do not work
window.addEventListener("touchstart", wheelHandler);
window.addEventListener("touchmove", wheelHandler);
window.addEventListener("touchend", wheelHandler);
window.addEventListener("touchcancel", wheelHandler);
}
function setStickyContainersSize(){
document.querySelectorAll('.sticky-container').forEach(function(container){
const stikyContainerHeight = (container.querySelector('main').offsetWidth + window.innerHeight);
container.setAttribute('style', 'height: ' + stikyContainerHeight + 'px');
});
}
function isElementInViewport (el) {
const rect = el.getBoundingClientRect();
return rect.top <= 0 && rect.bottom > document.documentElement.clientHeight;
}
function wheelHandler(evt){
const containerInViewPort = Array.from(document.querySelectorAll('.sticky-container')).filter(function(container){
return isElementInViewport(container);
})[0];
if(!containerInViewPort){
return;
}
var isPlaceHolderBelowTop = containerInViewPort.offsetTop < document.documentElement.scrollTop;
var isPlaceHolderBelowBottom = containerInViewPort.offsetTop + containerInViewPort.offsetHeight > document.documentElement.scrollTop;
let g_canScrollHorizontally = isPlaceHolderBelowTop && isPlaceHolderBelowBottom;
if(g_canScrollHorizontally){
containerInViewPort.querySelector('main').scrollLeft += evt.deltaY;
}
}
})();
html,
body {
margin: 0;
font-family: sans-serif;
}
.vertical-section{
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
main {
overflow-x: hidden;
display: flex;
position: sticky;
top:0;
}
h1 {
margin: 0;
padding: 0;
}
section {
min-width: 50vw;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-size: 4ch;
}
section:nth-child(even) {
background-color: teal;
color: white;
}
<div class="vertical-section">
scrolling is vertical
</div>
<div class="sticky-container">
<main>
<section>
<h1>scrolling</h1>
</section>
<section>
<h1>is</h1>
</section>
<section>
<h1>now</h1>
</section>
<section>
<h1>horizontal</h1>
</section>
</main>
</div>
<div class="vertical-section">
scrolling is vertical again
</div>
<div class="sticky-container">
<main>
<section>
<h1>scrolling</h1>
</section>
<section>
<h1>is</h1>
</section>
<section>
<h1>now</h1>
</section>
<section>
<h1>horizontal</h1>
</section>
</main>
</div>
How can I make this work for mobile touch, scroll bar, arrow keys, and page up/down?
Thanks
Upvotes: 0
Views: 1533
Reputation: 624
My solution was to use the scroll event, it works on all devices:
let lastKnownScrollPosition = 0;
let deltaY = 0;
window.addEventListener("scroll", wheelHandler);
document.querySelectorAll('.sticky-container').forEach(function(container) {
const stikyContainerHeight = (container.querySelector('main').offsetWidth + window.innerHeight);
container.setAttribute('style', 'height: ' + stikyContainerHeight + 'px');
});
function isElementInViewport(el) {
const rect = el.getBoundingClientRect();
return rect.top <= 0 && rect.bottom > document.documentElement.clientHeight;
}
function wheelHandler(event) {
deltaY = window.scrollY - lastKnownScrollPosition;
lastKnownScrollPosition = window.scrollY;
console.log('deltaY', deltaY);
const containerInViewPort = Array.from(document.querySelectorAll('.sticky-container')).filter(function(container) {
return isElementInViewport(container);
})[0];
if (!containerInViewPort) {
return;
}
var isPlaceHolderBelowTop = containerInViewPort.offsetTop < document.documentElement.scrollTop;
var isPlaceHolderBelowBottom = containerInViewPort.offsetTop + containerInViewPort.offsetHeight > document.documentElement.scrollTop;
let g_canScrollHorizontally = isPlaceHolderBelowTop && isPlaceHolderBelowBottom;
if (g_canScrollHorizontally) {
containerInViewPort.querySelector('main').scrollLeft += deltaY;
}
}
Upvotes: 2