이미지 슬라이더 만들기
38가지 자바스크립트&리액트 튜토리얼 15번째, 이미지 슬라이더 만들기
이거는.. 이전에 리뷰 캐러셀 만들기를 그냥 누르면 바뀌는 건데 슬라이드로 만들어버려서..
할까 안할까 했지만.. 리마인드 하는 느낌으로 조금 더 상세하게 설명하면서 진행하기로 했다.
이미지 슬라이더의 방식은 대체로 다 비슷비슷해서,
한번 익혀두면 요긴하게 쓸 수 있고, 기존 슬라이더들에 대한 이해도도 올라가서 좋을 것 같다.
작업 개요
이미지 슬라이더 구조의 핵심은 쭉 나열된 이미지와, 그 이미지가 보여질 칸이다.
쉽게 그림으로 설명해보면
저런식으로 쭉 나열된 이미지를, 틀에 맞춰서 이동 시켜 가면서 보여주면 된다.
HTML
위의 구조를 html과 css로 작성을 해보면,
<div class="container"> // 틀
<div class="wrapper"> // 이미지 롤을 감싸는 div
<div>Img01</div> // 이미지
<div>Img02</div> // 이미지
<div>Img03</div> // 이미지
</div>
</div>
구분하기 쉽게 틀에는 빨간 border, 이미지 롤 전체에는 초록 border, 각각의 이미지에는 파란색 border를 적용해보면
아래와 같이 표현된다.
여기서 이제,
.container에 position: relative,
.wrapper div에 position: absolute, display: flex; 를 주면, 아래와 같이 표현된다.
틀이될 div에는 width와 height 속성을 부여해주어야 한다.
.container에 width: 300px; height: 300px을 주면
이런식으로 나오게 되고, 이미지가 틀에 꽉 차게 나와야 하기 때문에,
각각의 이미지에도 width: 300px, height: 300px을 주어야 한다.
그리고, 빨간색 영역(틀) 밖으로 나가는 부분은 숨겨져야 하니
.container에 overflow: hidden; 속성을 주자.
화면상에 보이진 않지만 이전 모양새 처럼 틀 뒷쪽으로 숨겨져 있다.
.wrapper에 left: 0; 속성을 주고,
이해를 돕기 위해 임시로 애니메이션을 넣어 transform: translateX(value); 속성으로 움직임을 줘보면 아래와 같다.
wrapper에 transition 속성을 주고 left를 변경해서 움직여도 괜찮지만,
trasnform 속성으로 움직여주는게 애니메이션 퍼포먼스상 더 좋다고 하니 transform을 사용하자.
transform: translateX로 움직임을 줄때는, 본체를 기준으로 우측으로 움직이려면 양수로,
좌측으로 움직이려면 음수로 값을 주면 된다.
즉 translateX 속성이 0일때는 1번 이미지가 표시 되는 상태고,
여기서 2번 이미지를 보여주고 싶으면 이미지의 가로 사이즈 만큼인 -300px을 해주면 2번이미지가,
3번 이미지는 -300px * 2로 -600px을 잡아주면 2번 이미지가 나오게 된다.
이제 이미지 틀을 가운데 정렬로 맞춰주고, 아랫쪽에 간단하게 next, prev 버튼을 만들고 간단한 이미지 몇장을 넣어보자.
이상태에선 아직, 작동을 하지 않으니 이제 스크립트를 작성해보자.
JS
먼저 해야할건 transform: translateX 속성에 .wrapper 혹은 img의 가로 px 만큼 next일때는 빼주고,
prev일때는 더해주면되고, 각각 동작에서 curIdx 를 증감시켜준다.
let curIdx = 0; // 현재 페이지 번호
const wrapper = document.querySelector('.wrapper')
const wrapperWidth = wrapper.parentNode.offsetWidth;
const handleNext = () => {
curIdx ++
wrapper.style.transform = `translateX(${curIdx * -wrapperWidth}px`
}
const handlePrev = () => {
curIdx --
wrapper.style.transform = `translateX(${curIdx * -wrapperWidth}px`
}
이런식으로 작성을 해보고, next와 prev 버튼에 onclick 속성으로 추가해보면,
이제 next, prev가 동작하지만 뭔가 이상하다.
curIdx가 0이하로 내려가지 않고 최대(2) 슬라이드 이상으론 올라가지 않게 예외처리를 해보자.
let curIdx = 0; // 현재 페이지 번호
const wrapper = document.querySelector('.wrapper')
const wrapperWidth = wrapper.parentNode.offsetWidth;
const slideLength = wrapper.querySelectorAll('div').length;
const handleNext = () => {
if(slideLength-1 >= curIdx) return;
curIdx ++
wrapper.style.transform = `translateX(${curIdx * -wrapperWidth}px`
}
const handlePrev = () => {
if(0 >= curIdx) return;
curIdx --
wrapper.style.transform = `translateX(${curIdx * -wrapperWidth}px`
}
이러면 제대로 동작한다.