728x90
기본적인 아이디어는 아래 링크로 걸어둔 Easing 기법을 이용한다.
https://spicyyoghurt.com/tools/easing-functions
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>자바스크립트 연습</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="actions">
<span class="prev"><</span>
<span class="next">></span>
</div>
<div class="carousel">
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
<div class="card">5</div>
<div class="card">6</div>
<div class="card">7</div>
<div class="card">8</div>
<div class="card">9</div>
<div class="card">10</div>
<div class="card">11</div>
<div class="card">12</div>
<div class="card">13</div>
<div class="card">14</div>
<div class="card">15</div>
<div class="card">16</div>
<div class="card">17</div>
<div class="card">18</div>
<div class="card">19</div>
<div class="card">20</div>
</div>
</div>
<script src='app.js'></script>
</body>
</html>
.container{
width: 50%; height: 300px;
position: relative;
}
span{
position: absolute;
top: 50%; transform: translateY(-50%);
color: white;
font-size: 2rem;
background-color: rgba(0, 0, 0, .3);
width: 50px; height: 50px;
border-radius: 50%;
text-align: center;
cursor: pointer;
}
span.prev{
left: 1rem;
}
span.next{
right: 1rem;
}
.carousel{
width: 100%; height: 100%;
display: flex;
grid-gap: 10px;
background-color: bisque;
overflow-x: scroll;
}
.card{
min-width: 200px; height: 100%;
background-color: aquamarine;
text-align: center;
line-height: 300px;
font-weight: bold;
font-size: 10rem;
color: white;
/* border: 1px solid red; */
}
아래와 같이 setInterval 타이머를 걸어두고 스크롤이 끝나기 전에 다시 next 버튼을 클릭하면 타이머가 새로 생성되면서 timer id 가 새로 할당된다. 이렇게 되면 스크롤이 끝났을때 새로 생성된 타이머는 해제가 되지만 이전에 생성된 타이머는 ID 값을 더이상 조회할 수 없기 때문에 해제되지 않고 백그라운드에서 계속 실행된다. 그래서 스크롤이 멈추지 않고 반복적으로 계속 실행된다.
const prevBtn = document.querySelector('.prev')
const nextBtn = document.querySelector('.next')
const carousel = document.querySelector('.carousel')
let timerId = null
let currentTime = 0
function changePosition(unitTime, start, destination){
currentTime += unitTime
if(currentTime < 1){
console.log('ongoing')
carousel.scrollLeft = easeOutExpo(currentTime, start, destination, 1)
// nextBtn.removeEventListener('click', toNextSlides)
}else{
console.log('end')
currentTime = 0
clearInterval(timerId)
// nextBtn.addEventListener('click', toNextSlides)
}
}
function toNextSlides(){
timerId = setInterval(() => changePosition(0.03, 0, 500), 100)
}
prevBtn.addEventListener('click', function(){
})
nextBtn.addEventListener('click', toNextSlides)
function easeOutExpo (t, b, c, d) {
return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
}
이런 문제를 해결하려면 스크롤이 되고 있는중에는 사용자가 버튼을 클릭하지 못하도록 잠깐 클릭 이벤트를 해제했다가 스크롤이 끝났을때 다시 등록해야 한다.
const prevBtn = document.querySelector('.prev')
const nextBtn = document.querySelector('.next')
const carousel = document.querySelector('.carousel')
let timerId = null
let currentTime = 0
function changePosition(unitTime, start, destination){
currentTime += unitTime
if(currentTime < 1){
console.log('ongoing')
carousel.scrollLeft = easeOutExpo(currentTime, start, destination, 1)
nextBtn.removeEventListener('click', toNextSlides)
}else{
console.log('end')
currentTime = 0
clearInterval(timerId)
nextBtn.addEventListener('click', toNextSlides)
}
}
function toNextSlides(){
timerId = setInterval(() => changePosition(0.03, 0, 500), 100)
}
prevBtn.addEventListener('click', function(){
})
nextBtn.addEventListener('click', toNextSlides)
function easeOutExpo (t, b, c, d) {
return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
}
728x90
'프론트엔드 > 컴포넌트' 카테고리의 다른 글
부드러운 가로 스크롤링 (3) - ease 함수 사용 (0) | 2023.07.06 |
---|---|
로딩 애니메이션 (0) | 2023.07.05 |
부드러운 가로 스크롤링 (0) | 2023.06.27 |
자동 슬라이드 만들기 (1) (0) | 2023.04.24 |
자바스크립트없이 드롭다운 메뉴 만들기 (3) (0) | 2023.04.14 |