- 이미 풀페이지 스크롤이 구현되어있는 상태
- 특정 페이지내에서 슬라이드가 세로로 스크롤되는 구조로 만들어야 하는데, 풀페이지 스크롤 기능과 겹쳐 스크롤 이벤트를 구현하는데 쉽지 않았다..
- 해당 페이지에 도달하면 body 의 스크롤을 막은 후 슬라이드를 실행하게 하고, 슬라이드가 끝나면 다시 body 의 스크롤이 실행되게끔 하는 구조로 만들어보았다.
<main id="contents" style="max-width: 100%">
<div class="page1">페이지1</div>
<div class="page2">페이지2</div>
<div class="page3">
<h2>페이지3</h2>
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide active">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
</div>
<div class="pagination-test"></div>
</div>
</div>
<div class="page4">페이지4</div>
</main>
.page3 {position: relative; }
.page3 .swiper-slide {position: absolute; width: 100%; top: 0; left: 0; height: 100vh; opacity: 0; transition: .3s;}
.page3 .swiper-slide.active {opacity: 1;}
.page3 .swiper-slide:nth-child(1) {background-color: darksalmon}
.page3 .swiper-slide:nth-child(2) {background-color: green}
.page3 .swiper-slide:nth-child(3) {background-color: gold}
removeEventListener
를 통해 이벤트 제거// 스크롤 이벤트(페이지)
const page_03 = document.querySelector('.page3');
const page_03Top = page_03.offsetTop;
window.addEventListener('scroll', function() {
const windowY = window.scrollY;
setTimeout(() => {
if (sdCut_08Top <= windowY && windowY <= sdCut_08Top + 100) {
// 스크롤 방지
$body.addEventListener('wheel', preventScroll, { passive: false });
console.log('dd')
}
if (!sdCut_08.classList.contains('currentActive')) {
$body.removeEventListener('wheel', preventScroll, { passive: false });
}
}, 500)
});
deltaY
를 사용하여 휠의 방향에 따라 기능을 줄 수 있었다.// 마우스휠 이벤트(슬라이드)
let activeIndex = 0; // [0, 1, 2]
const $body = document.querySelector('body');
const slideArr = Array.from(document.querySelectorAll('.swiper-slide'));
sdCut_08.addEventListener('mousewheel', function(e) {
if (e.deltaY > 0) { // 마우스 휠 down
if (activeIndex !== slideArr.length - 1) {
activeIndex = slideArr.findIndex((slide) => slide.classList.contains('active'))
slideArr[activeIndex].classList.remove('active')
slideArr[activeIndex + 1].classList.add('active')
activeIndex = activeIndex + 1;
console.log('down')
} else {
$body.removeEventListener('wheel', preventScroll, { passive: false });
}
} else if (e.deltaY < 0) { // 마우스 휠 up
if (activeIndex !== 0) {
activeIndex = slideArr.findIndex((slide) => slide.classList.contains('active'))
slideArr[activeIndex].classList.remove('active')
slideArr[activeIndex - 1].classList.add('active')
activeIndex = activeIndex - 1;
console.log('up')
} else {
$body.removeEventListener('wheel', preventScroll, { passive: false });
}
}
})
function _throttle(callback, delay) {
let timeoutId;
return function() {
if (!timeoutId) {
// 지정된 시간이 지나면 콜백을 실행하고 timeoutId를 재설정
timeoutId = setTimeout(function() {
callback.apply(null, arguments);
timeoutId = null;
}, delay);
}
};
}
하지만 스크롤 이벤트에는 잘 작동되어서, 마우스휠 이벤트(슬라이드) 이벤트에도 똑같이 적용해줬더니 다음과 같은 에러가 발생했다.
const throttledMousewheelHandler = _throttle(function(e) {
console.log(e) // undefined
if (e.deltaY > 0) { // 마우스 휠 down
...
} else if (e.deltaY < 0) { // 마우스 휠 up
...
}
}, 500);
처음 적용한 스크롤 이벤트에는 이벤트객체(e) 를 사용하지 않았고, 두번째 함수에서는 이벤트객체를 사용하여 e 가 undefined
로 나타난것이었다.
그래서 아래와같이 throttle 의 콜백함수에 이벤트 객체를 인수로 넣어준 후 다시 작동시켰더니 잘 작동이 되었다.
⇒ return function(...args)
// throttle 함수 정의
function _throttle(callback, delay) {
let timeoutId;
return function(...args) { // ...args 에 이벤트 객체(e)가 들어감
if (!timeoutId) {
timeoutId = setTimeout(function() {
callback.apply(null, args);
timeoutId = null;
}, delay);
}
};
}
// script
// 슬라이드 스크롤 ----------------------------
// throttle 함수 정의
function _throttle(callback, delay) { // delay 에는 속도가 들어감
let timeoutId;
return function(...args) { // ...args 에 이벤트 객체(e)가 들어감
if (!timeoutId) {
// 지정된 시간이 지나면 콜백을 실행하고 timeoutId를 재설정
timeoutId = setTimeout(function() {
callback.apply(null, args);
timeoutId = null;
}, delay);
}
};
}
let activeIndex = 0; // [0, 1, 2]
const $body = document.querySelector('body');
const slideArr = Array.from(document.querySelectorAll('.swiper-slide'));
const page_03 = document.querySelector('.page3');
const page_03Top = page_03.offsetTop;
function preventScroll(e) {
e.preventDefault();
}
// 스크롤 이벤트 핸들러
const throttledScrollHandler = _throttle(function() {
const windowY = window.scrollY;
if (page_03Top <= windowY && windowY <= page_03Top + 100) {
// 스크롤 방지
$body.addEventListener('wheel', preventScroll, { passive: false });
console.log('dd');
}
if (!page_03.classList.contains('currentActive')) {
$body.removeEventListener('wheel', preventScroll, { passive: false });
}
}, 500);
window.addEventListener('scroll', throttledScrollHandler);
const throttledMousewheelHandler = _throttle(function(e) {
if (e.deltaY > 0) { // 마우스 휠 down
if (activeIndex !== slideArr.length - 1) {
activeIndex = slideArr.findIndex((slide) => slide.classList.contains('active'))
slideArr[activeIndex].classList.remove('active')
slideArr[activeIndex + 1].classList.add('active')
activeIndex = activeIndex + 1;
console.log('down')
} else {
$body.removeEventListener('wheel', preventScroll, { passive: false });
}
} else if (e.deltaY < 0) { // 마우스 휠 up
if (activeIndex !== 0) {
activeIndex = slideArr.findIndex((slide) => slide.classList.contains('active'))
slideArr[activeIndex].classList.remove('active')
slideArr[activeIndex - 1].classList.add('active')
activeIndex = activeIndex - 1;
console.log('up')
} else {
$body.removeEventListener('wheel', preventScroll, { passive: false });
}
}
}, 500);
page_03.addEventListener('mousewheel', throttledMousewheelHandler);
// 화면이 resize 되었을 때
window.addEventListener('resize', function() {
sdCut_08Top = sdCut_08.offsetTop;
window.addEventListener('scroll', throttledScrollHandler);
sdCut_08.addEventListener('mousewheel', throttledMousewheelHandler);
});
// 풀페이지 스크롤
function startScrollFullPage() {
//풀페이지 스크롤되는 코드
}
startScrollFullPage()