728x90
https://www.javascripttutorial.net/javascript-dom/javascript-width-height/
https://stackoverflow.com/questions/6338217/get-a-css-value-with-javascript
기본적인 아이디어는 현재 컨테이너 너비를 아이템 너비로 나눠서 현재 컨테이너에 몇개의 아이템(갯수)이 보이는지 알아낸다. 이전과 다음 버튼을 클릭했을때 현재 위치(currentPosition)에서 보이는 갯수만큼 더하거나 빼준다. 현재 위치에 있는 요소로 스크롤한다. box-sizing: border-box 로 설정해서 패딩과 보더는 width 안에 포함되도록 하면 계산이 편하다. 마진만 신경쓰면 되는데 마진은 자바스크립트로 css 에 설정된 값이 얼마인지 가져올 수 있다. 아이템 너비로 나눠줄때 아이템 너비에 마진도 포함한다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Slideshow</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="wrapper">
<div class="container">
<div class="item"><a href="#">1 - Lorem ipsum dolor sit amet consectetur</a></div>
<div class="item"><a href="#">2 - Lorem ipsum dolor sit amet consectetur</a></div>
<div class="item"><a href="#">3 - Lorem ipsum dolor sit amet consectetur</a></div>
<div class="item"><a href="#">4 - Lorem ipsum dolor sit amet consectetur</a></div>
<div class="item"><a href="#">5 - Lorem ipsum dolor sit amet consectetur</a></div>
<div class="item"><a href="#">6 - Lorem ipsum dolor sit amet consectetur</a></div>
<div class="item"><a href="#">7 - Lorem ipsum dolor sit amet consectetur</a></div>
<div class="item"><a href="#">8 - Lorem ipsum dolor sit amet consectetur</a></div>
<div class="item"><a href="#">9 - Lorem ipsum dolor sit amet consectetur</a></div>
<div class="item"><a href="#">10 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">11 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">12 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">13 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">14 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">15 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">16 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">17 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">18 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">19 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">20 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">21 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">22 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">23 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">24 - Lorem ipsum dolor sit amet consectetu</a></div>
<div class="item"><a href="#">25 - Lorem ipsum dolor sit amet consectetu</a></div>
</div>
<div class="actions">
<button><</button>
<button>></button>
</div>
</div>
<script>
let currentPosition = null
const container = document.querySelector('.container')
const item = document.querySelector('.container .item')
const btns = document.querySelectorAll('.actions button')
const numOfItems = document.querySelectorAll('.container .item').length
console.log(numOfItems)
// get margin of item
const style = window.getComputedStyle(item)
const itemMargin = parseInt(style.getPropertyValue('margin'))
console.log(itemMargin)
btns[0].addEventListener('click', function(){
console.log('container:', container.getBoundingClientRect())
console.log('item:', item.getBoundingClientRect())
const containerWidth = container.getBoundingClientRect().width
const itemWidth = item.getBoundingClientRect().width
const numOfItemsToMove = Math.floor(containerWidth / (itemWidth + 2 * itemMargin))
if(currentPosition >= numOfItemsToMove) currentPosition -= numOfItemsToMove
console.log(currentPosition)
const elementToScroll = document.querySelectorAll('.container .item')[currentPosition]
if(elementToScroll) elementToScroll.scrollIntoView({ behavior: 'smooth', inline: 'start' })
})
btns[1].addEventListener('click', function(){
console.log('container:', container.getBoundingClientRect())
console.log('item:', item.getBoundingClientRect())
const containerWidth = container.getBoundingClientRect().width
const itemWidth = item.getBoundingClientRect().width
// scrollBy 는 정확도가 좀 떨어짐
// const numOfItems = Math.floor(containerWidth / itemWidth)
// console.log(numOfItems)
// container.scrollBy({ left: numOfItems * itemWidth, behavior: 'smooth' })
// const orderToScroll = Math.floor(containerWidth / itemWidth)
// console.log(orderToScroll)
// const elementToScroll = document.querySelectorAll('.container .item')[orderToScroll*cnt]
// if(elementToScroll) elementToScroll.scrollIntoView({ behavior: 'smooth', inline: 'start' })
const numOfItemsToMove = Math.floor(containerWidth / (itemWidth + 2 * itemMargin))
if(currentPosition < numOfItems - 1) currentPosition += numOfItemsToMove
console.log(currentPosition)
const elementToScroll = document.querySelectorAll('.container .item')[currentPosition]
if(elementToScroll) elementToScroll.scrollIntoView({ behavior: 'smooth', inline: 'start' })
})
</script>
</body>
</html>
*{
box-sizing: border-box;
}
.wrapper{
width: 35%;
position: relative;
display: inline-block;
}
.container{
height: 200px;
border: 3px solid #333;
display: flex;
overflow: scroll;
}
.wrapper .actions button{
position: absolute;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
width: 30px; height: 30px;
border-radius: 50%;
background-color: rgba(0, 0, 0, .3);
border: none;
}
.wrapper .actions button:nth-child(1){
left: 5px;
}
.wrapper .actions button:nth-child(2){
right: 5px;
}
.wrapper .actions button:hover{
background-color: rgba(0, 0, 0, .5);
}
.item{
background-color: #fff; color: #333;
border: 2px solid #333;
margin: 10px;
}
728x90
'프론트엔드 > 컴포넌트' 카테고리의 다른 글
로딩 애니메이션 (0) | 2023.07.05 |
---|---|
부드러운 가로 스크롤링 (2) (0) | 2023.07.05 |
자동 슬라이드 만들기 (1) (0) | 2023.04.24 |
자바스크립트없이 드롭다운 메뉴 만들기 (3) (0) | 2023.04.14 |
자바스크립트없이 드롭다운 메뉴 만들기 (2) (0) | 2023.04.14 |