#
25.가로스크롤
#
목차
1. 가로방향 스크롤 1.1. 예제 1.1.1. 가로방향 1.1.2. 가로+세로 스티키
#
1. 가로방향 스크롤
횡스크롤을 제작해보자
#
1.1. 예제
#
1.1.1. 가로방향
<main>
<section>
<h1>Boop</h1>
</section>
<section>
<h1>Boooom</h1>
</section>
<section>
<h1>Boooom</h1>
</section>
<section>
<h1>The End</h1>
</section>
</main>
html,
body {
margin: 0;
font-family: sans-serif;
}
main {
overflow-x: hidden;
display: flex;
}
section {
min-width: 100vw;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-size: 4em;
}
section:nth-child(even) {
background-color: teal;
color: white;
}
const scrollContainer = document.querySelector('main');
scrollContainer.addEventListener('wheel', (e) => {
e.preventDefault();
//scrollLeft 요소의 수평 스크롤 바 위치를 반환 , e.deltaY 스크롤방향을 반환 (우측:100,좌측:-100)
//scrollContainer의 수평 스크롤 바 위치에 스크롤 방향을 합하여 가로스크롤양이 가산되며 이동한다.
let amt = (scrollContainer.scrollLeft += e.deltaY);
});
부드러운 이동 실행화면
const scrollContainer = document.querySelector('main');
let target = 0;
let ease = 0.1; // 부드러운 이동을 위한 변화 정도
// 부드럽게 이동하는 함수
function smoothScroll() {
scrollContainer.scrollLeft += (target - scrollContainer.scrollLeft) * ease;
requestAnimationFrame(smoothScroll); // 부드럽게 이동하도록 애니메이션 추가
}
scrollContainer.addEventListener('wheel', (e) => {
e.preventDefault();
target += e.deltaY; // 스크롤 목표 위치 변경
});
smoothScroll(); // 함수 실행
#
1.1.2. 가로+세로 스티키
<div class="vertical">HELLO</div>
<div class="sticky">
<main>
<section>
<h1>Beep</h1>
</section>
<section>
<h1>Boop</h1>
</section>
<section>
<h1>Boooom</h1>
</section>
<section>
<h1>The End</h1>
</section>
</main>
</div>
<div class="vertical">DEVELOPER</div>
<div class="sticky">
<main>
<section>
<h1>Beep</h1>
</section>
<section>
<h1>Boop</h1>
</section>
<section>
<h1>Boooom</h1>
</section>
<section>
<h1>The End</h1>
</section>
</main>
</div>
html,
body {
margin: 0;
font-family: sans-serif;
}
.vertical {
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;
}
(function () {
let g_canScroll;
init();
//초기화
function init() {
setSticky();
bindEvents();
}
function bindEvents() {
window.addEventListener('wheel', wheelHandler);
}
function setSticky() {
document.querySelectorAll('.sticky').forEach(function (container) {
// scrollWidth=전체 스크롤바를 사용하게 되어 숨겨진 영역까지 포함한 크기를 리턴
const stikyContainerHeight = container.querySelector('main').scrollWidth;
//.sticky의 높이를 각각 스크롤 너비와 같게 함
container.setAttribute('style', 'height: ' + stikyContainerHeight + 'px');
});
}
//요소가 화면에 들어왔는지를 확인하는 함수
function isInView(el) {
const rect = el.getBoundingClientRect();
//요소가 화면에 있을경운
console.log('document.documentElement', document.documentElement);
return rect.top <= 0 && rect.bottom > document.documentElement.clientHeight;
}
function wheelHandler(e) {
// https://ko.javascript.info/iterable
const elInView = Array.from(document.querySelectorAll('.sticky')).filter(function (el) {
return isInView(el);
})[0];
if (!elInView) {
return;
}
console.log('elInView', elInView);
let isPlaceHolderBelowTop = elInView.offsetTop < document.documentElement.scrollTop; //.sticky-container의 상단좌표를 스크롤보다 작은지 비교
let isPlaceHolderBelowBottom = elInView.offsetTop + elInView.offsetHeight > document.documentElement.scrollTop; //.sticky-container 탑과 높이를 합하고(길이) 스크롤양보다 큰지비교
g_canScroll = isPlaceHolderBelowTop && isPlaceHolderBelowBottom; //true 는 보이는 상태
console.log(elInView, elInView.offsetTop, isPlaceHolderBelowBottom);
elInView.querySelector('main').scrollLeft += e.deltaY;
}
})();