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:
JavaScript
x
53
53
1
(function(){
2
init();
3
4
var g_containerInViewport;
5
function init(){
6
setStickyContainersSize();
7
bindEvents();
8
}
9
10
function bindEvents(){
11
window.addEventListener("wheel", wheelHandler);
12
13
//do not work
14
window.addEventListener("touchstart", wheelHandler);
15
window.addEventListener("touchmove", wheelHandler);
16
window.addEventListener("touchend", wheelHandler);
17
window.addEventListener("touchcancel", wheelHandler);
18
19
20
}
21
22
function setStickyContainersSize(){
23
document.querySelectorAll('.sticky-container').forEach(function(container){
24
const stikyContainerHeight = (container.querySelector('main').offsetWidth + window.innerHeight);
25
container.setAttribute('style', 'height: ' + stikyContainerHeight + 'px');
26
});
27
}
28
29
function isElementInViewport (el) {
30
const rect = el.getBoundingClientRect();
31
return rect.top <= 0 && rect.bottom > document.documentElement.clientHeight;
32
}
33
34
function wheelHandler(evt){
35
36
37
const containerInViewPort = Array.from(document.querySelectorAll('.sticky-container')).filter(function(container){
38
return isElementInViewport(container);
39
})[0];
40
41
if(!containerInViewPort){
42
return;
43
}
44
45
var isPlaceHolderBelowTop = containerInViewPort.offsetTop < document.documentElement.scrollTop;
46
var isPlaceHolderBelowBottom = containerInViewPort.offsetTop + containerInViewPort.offsetHeight > document.documentElement.scrollTop;
47
let g_canScrollHorizontally = isPlaceHolderBelowTop && isPlaceHolderBelowBottom;
48
49
if(g_canScrollHorizontally){
50
containerInViewPort.querySelector('main').scrollLeft += evt.deltaY;
51
}
52
}
53
})();
JavaScript
1
38
38
1
html,
2
body {
3
margin: 0;
4
font-family: sans-serif;
5
}
6
7
.vertical-section{
8
height: 100vh;
9
display: flex;
10
align-items: center;
11
justify-content: center;
12
}
13
14
main {
15
overflow-x: hidden;
16
display: flex;
17
position: sticky;
18
top:0;
19
}
20
21
h1 {
22
margin: 0;
23
padding: 0;
24
}
25
26
section {
27
min-width: 50vw;
28
min-height: 100vh;
29
display: flex;
30
justify-content: center;
31
align-items: center;
32
font-size: 4ch;
33
}
34
35
section:nth-child(even) {
36
background-color: teal;
37
color: white;
38
}
JavaScript
1
38
38
1
<div class="vertical-section">
2
scrolling is vertical
3
</div>
4
<div class="sticky-container">
5
<main>
6
<section>
7
<h1>scrolling</h1>
8
</section>
9
<section>
10
<h1>is</h1>
11
</section>
12
<section>
13
<h1>now</h1>
14
</section>
15
<section>
16
<h1>horizontal</h1>
17
</section>
18
</main>
19
</div>
20
<div class="vertical-section">
21
scrolling is vertical again
22
</div>
23
<div class="sticky-container">
24
<main>
25
<section>
26
<h1>scrolling</h1>
27
</section>
28
<section>
29
<h1>is</h1>
30
</section>
31
<section>
32
<h1>now</h1>
33
</section>
34
<section>
35
<h1>horizontal</h1>
36
</section>
37
</main>
38
</div>
How can I make this work for mobile touch, scroll bar, arrow keys, and page up/down?
Thanks
Advertisement
Answer
My solution was to use the scroll event, it works on all devices:
JavaScript
1
45
45
1
let lastKnownScrollPosition = 0;
2
let deltaY = 0;
3
4
window.addEventListener("scroll", wheelHandler);
5
6
document.querySelectorAll('.sticky-container').forEach(function(container) {
7
const stikyContainerHeight = (container.querySelector('main').offsetWidth + window.innerHeight);
8
container.setAttribute('style', 'height: ' + stikyContainerHeight + 'px');
9
});
10
11
12
function isElementInViewport(el) {
13
const rect = el.getBoundingClientRect();
14
return rect.top <= 0 && rect.bottom > document.documentElement.clientHeight;
15
}
16
17
function wheelHandler(event) {
18
19
deltaY = window.scrollY - lastKnownScrollPosition;
20
lastKnownScrollPosition = window.scrollY;
21
22
23
console.log('deltaY', deltaY);
24
25
26
const containerInViewPort = Array.from(document.querySelectorAll('.sticky-container')).filter(function(container) {
27
return isElementInViewport(container);
28
})[0];
29
30
if (!containerInViewPort) {
31
return;
32
}
33
34
var isPlaceHolderBelowTop = containerInViewPort.offsetTop < document.documentElement.scrollTop;
35
var isPlaceHolderBelowBottom = containerInViewPort.offsetTop + containerInViewPort.offsetHeight > document.documentElement.scrollTop;
36
let g_canScrollHorizontally = isPlaceHolderBelowTop && isPlaceHolderBelowBottom;
37
38
39
if (g_canScrollHorizontally) {
40
41
containerInViewPort.querySelector('main').scrollLeft += deltaY;
42
43
}
44
}
45