【vanilla js】GSAPを使わずにスクロール途中で横スクロールさせる方法
2024.07.31
9
See the Pen 【vanilla js】GSAPを使わずにスクロール途中で横スクロールさせる方法 by WP TechLab. (@wptech-lab-com) on CodePen.
<section class="section sec1">
<p>sec1</p>
</section>
<section class="section sec2">
<div class="scroll_slide_container">
<div class="scroll_container_wrapper">
<div class="scroll_container">
<div class="scroll_item">item1</div>
<div class="scroll_item">item2</div>
<div class="scroll_item">item3</div>
<div class="scroll_item">item4</div>
<div class="scroll_item">item5</div>
<div class="scroll_item">item6</div>
<div class="scroll_item">item7</div>
<div class="scroll_item">item8</div>
<div class="scroll_item">item9</div>
<div class="scroll_item">item10</div>
</div>
</div>
</div>
</section>
<section class="section sec3">
<p>sec3</p>
</section>
<section class="section sec2">
<div class="scroll_slide_container">
<div class="scroll_container_wrapper">
<div class="scroll_container">
<div class="scroll_item">item1</div>
<div class="scroll_item">item2</div>
<div class="scroll_item">item3</div>
<div class="scroll_item">item4</div>
<div class="scroll_item">item5</div>
<div class="scroll_item">item6</div>
<div class="scroll_item">item7</div>
<div class="scroll_item">item8</div>
<div class="scroll_item">item9</div>
<div class="scroll_item">item10</div>
<div class="scroll_item">item11</div>
<div class="scroll_item">item12</div>
<div class="scroll_item">item13</div>
<div class="scroll_item">item14</div>
<div class="scroll_item">item15</div>
<div class="scroll_item">item16</div>
<div class="scroll_item">item17</div>
<div class="scroll_item">item18</div>
<div class="scroll_item">item19</div>
<div class="scroll_item">item20</div>
</div>
</div>
</div>
</section>
<section class="section sec3">
<p>sec5</p>
</section>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.section {
display: block;
width: 100%;
overflow-x: clip;
}
.sec1,
.sec3 {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
background-color: #eee;
}
.scroll_slide_container {
position: relative;
display: flex;
align-items: flex-start;
width: 100%;
color: #fff;
min-height: 100vh;
}
.scroll_container_wrapper {
position: sticky;
top: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
width: 100%;
height: 100vh;
}
.scroll_container {
display: flex;
align-items: flex-start;
gap: 20px;
width: 100%;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
height: 400px;
}
.scroll_item {
display: flex;
align-items: center;
justify-content: center;
width: 600px;
height: 400px;
flex-shrink: 0;
background-color: #191919;
}
document.addEventListener("DOMContentLoaded", () => {
initializeSliders();
setInitialScrollPositions();
});
const initializeSliders = () => {
const scrollSlideContainers = document.querySelectorAll('.scroll_slide_container');
scrollSlideContainers.forEach(scrollSlideContainer => {
const scrollContainerWrapper = scrollSlideContainer.querySelector('.scroll_container_wrapper');
const scrollContainer = scrollSlideContainer.querySelector('.scroll_container');
const scrollSlideContainerTop = scrollSlideContainer.getBoundingClientRect().top + window.pageYOffset;
const WindowWidth = window.innerWidth;
const WindowHeight = window.innerHeight;
const WindowHalfHeight = WindowHeight / 2;
const scrollContainerWrapperHeight = scrollContainerWrapper.offsetHeight;
const scrollContainerWidth = scrollContainer.scrollWidth;
scrollSlideContainer.style.height = `${scrollContainerWidth + (window.innerWidth - document.body.clientWidth)}px`;
let rootMargin = `-${(WindowHalfHeight) - (scrollContainerWrapperHeight / 2)}px 0px`;
const observerOptions = {
root: null,
rootMargin: rootMargin,
threshold: [1]
};
let scrollListenerAdded = false;
let ticking = false;
const handleScroll = () => {
if (!ticking) {
window.requestAnimationFrame(() => {
let translateX = scrollSlideContainerTop - window.scrollY + (window.innerWidth - document.body.clientWidth);
translateX = Math.min(0, Math.max(translateX, -(scrollContainerWidth - WindowWidth + (window.innerWidth - document.body.clientWidth))));
scrollContainer.style.transform = `translateX(${translateX}px)`;
ticking = false;
});
ticking = true;
}
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.intersectionRatio === 1) {
scrollContainer.style.position = "fixed";
if (!scrollListenerAdded) {
scrollListenerAdded = true;
window.addEventListener('scroll', handleScroll);
}
} else {
if (scrollListenerAdded) {
scrollContainer.style.position = "";
scrollListenerAdded = false;
window.removeEventListener('scroll', handleScroll);
}
}
});
}, observerOptions);
observer.observe(scrollContainerWrapper);
setInitialScrollPosition(scrollSlideContainer, scrollContainer, scrollSlideContainerTop, scrollContainerWidth, WindowWidth);
});
};
const setInitialScrollPosition = (scrollSlideContainer, scrollContainer, scrollSlideContainerTop, scrollContainerWidth, WindowWidth) => {
const initialScrollPosition = window.scrollY;
if (initialScrollPosition >= scrollSlideContainerTop && initialScrollPosition <= (scrollSlideContainerTop + scrollContainerWidth - WindowWidth)) {
let translateX = scrollSlideContainerTop - initialScrollPosition + (window.innerWidth - document.body.clientWidth);
translateX = Math.min(0, Math.max(translateX, -(scrollContainerWidth - WindowWidth + (window.innerWidth - document.body.clientWidth))));
scrollContainer.style.transform = `translateX(${translateX}px)`;
} else if (initialScrollPosition > (scrollSlideContainerTop + scrollContainerWidth - WindowWidth)) {
let translateX = -(scrollContainerWidth - WindowWidth + (window.innerWidth - document.body.clientWidth));
scrollContainer.style.transform = `translateX(${translateX}px)`;
}
};
const setInitialScrollPositions = () => {
const scrollSlideContainers = document.querySelectorAll('.scroll_slide_container');
scrollSlideContainers.forEach(scrollSlideContainer => {
const scrollContainer = scrollSlideContainer.querySelector('.scroll_container');
const scrollSlideContainerTop = scrollSlideContainer.getBoundingClientRect().top + window.pageYOffset;
const scrollContainerWidth = scrollContainer.scrollWidth;
const WindowWidth = window.innerWidth;
setInitialScrollPosition(scrollSlideContainer, scrollContainer, scrollSlideContainerTop, scrollContainerWidth, WindowWidth);
});
};