스터디 과정중 자기소개 페이지의 좌우 슬라이더를 구현할 일이 생겼다. 요 슬라이더를 매우
간단하게 슬라이더 라이브러리인 swiper.js로 간단하게 슬라이드를 구현할 수 있지만
아직은 배우는 단계이므로 순수 자바스크립트로만 구현을 해보자
전체적인 코드를 간략하게 나타낸 알고리즘이다. - 파란색은 함수를 나타낸다.
로직을보면서 조금더 자세히 알고리즘을 설명하려고 한다.
화면상 보이는 크기를 Slides
라고 잡고 이것이 움직이면서 좌우 슬라이드를 구현할것이다.
하지만 이상태에서는 슬라이더를 구현하기가 힘드니 Slide
개수만큼 앞뒤 복사하여 붙여준다.
function makeClone() {
currentIdx = 0;
for (let i = 0; i < slideCount; i++) {
let cloneSlide = slide[i].cloneNode(true);
slides.appendChild(cloneSlide);
}
for (let i = slideCount - 1; i >= 0; i--) {
let cloneSlide = slide[i].cloneNode(true);
slides.prepend(cloneSlide);
}
setInitialPos();
setTimeout(function () {
slides.classList.add('animated');
}, 10)
}
makeClone함수를 붙여 Slide
개수만큼 앞뒤 복사하여 붙여 놓는다.
slide
복사본을 앞뒤에 붙여 놓았으나 지금 현재 slides
의 위치가 복사본 첫번째 위치에 있기때문에 이경우 왼쪽 버튼을 클릭했을때, 빈 공간이 나오기 때문에 setInitialPos()
함수를 이용해 가운데 위치로 보내줘야한다.
slideMargin
과slidesWidth
값을 계산해서 initialTranslateValue
라는 변수에 넣어주고 트랜스폼을 이용하여 그 위치만금 이동을 하게되면 가운데 위치를 선정할 수 있다.
slides.style.transform = 'translateX(' + initialTranslateValue + 'px)';
그러고 나서 오른쪽 버튼과 왼쪽 버튼을 눌러 slides
를 움직여 좌우 슬라이드를 만들수 있다.
이제 slides
를 움직여줄 moveSlide()
함수를 생성해서 left값을 조정한다.
function moveSlide(num) {
slides.style.left = -num * (slideWidth + slideMargin) + 'px';
currentIdx = num;
}
left값 만큼 움직였지만 마지막 복사본 끝이나 처음으로 갔을 경우 복사본을 또 다시 넣을경우 코드가 매우 난잡해지기 때문에 기존에 있던 위치로 이동 할것이다.
slideCount
를 슬라이드 개수 currentIdx
를 이동한 횟수로 변수로 두자.
slideCount
와 currentIdx
가 "서로 같다면" 이라는 조건하에 움직이면 되겠다.
반대로 오른쪽이 아닌 왼쪽으로 슬라이더 할 경우도 있으니 currentIdx == -slideCount
를 추가해준다.
기존에 있던 곳으로 이동하면서 currentIdx
를 0으로 초기화 해주고 animated
라는 클래스를 지우고 1초뒤 다시 생성해준다.
그래서 moveSlide()
함수가 완성되었다.
function moveSlide(num) {
slides.style.left = -num * (slideWidth + slideMargin) + 'px';
currentIdx = num;
if (currentIdx == slideCount || currentIdx == -slideCount) {
setTimeout(function () {
slides.classList.remove('animated');
slides.style.left = '0px';
currentIdx = 0;
}, 500);
setTimeout(function () {
slides.classList.add('animated');
}, 600);
}
}
이제moveSlide()
함수를 사용할 버튼 이벤트 리스너를 추가해준다
다음 버튼을 누르면currentIdx
을 증가 시켜줘서 다음 슬라이드로 넘어간다.
반대로 이전 버튼을 누르면 currentIdx
을 감소 시켜줘서 이전 슬라이드로 넘어간다.
nextBtn.addEventListener('click', () => {
moveSlide(currentIdx + 1);
});
prevBtn.addEventListener('click', () => {
moveSlide(currentIdx - 1);
});
그다음 첫번째 보고있는 화면을 큰 이미지로 출력 시켜보려면 어떻게 해야할까
우선 addImage()
함수를 생성 시켜 num
숫자 파라미터 값을 받는다.
num의 숫자를 받아와서 배열안에 알맞는 인덱스에 맞춰서 사진을 꺼낸다.
function addImage(num) {
bigImage.style.background = `center url(${contentArr[num]}) no-repeat`;
}
하지만 배열은 0번 인덱스부터 가지고 있어 currentIdx와 SlideCount가 서로 같아지는 시점이 되면 사진은 다른 인덱스를 호출하여 엉뚱한 이미지를 가져온다.
그래서 nextBtn
이벤트 리스너 안에 if (currentIdx == slideCount) addImage(0);
를 넣는다.
슬라이더가 다 돌고 currentIdx
와 slideCount
가 같아졌을때 0번 인덱스의 사진을 호출 시킨다.
nextBtn.addEventListener('click', () => {
moveSlide(currentIdx + 1);
if (currentIdx == slideCount) {
addImage(0);
} else addImage(currentIdx);
});
이랬을 경우 prevBtn
역시 배열을 통해 호출을 하다 보니 currentIdx
가 음수가 되어버리면 배열은 음수 인덱스가 존재하지 않으니 아무것도 출력하지 않는다. 그래서 음수가 됐을때 slideCount
를 추가해주면 해결이 가능하다.
prevBtn.addEventListener('click', () => {
moveSlide(currentIdx - 1);
if (currentIdx < 0) {
addImage(currentIdx + slideCount);
} else addImage(currentIdx);
});
- 가독성 좋고 설명을 잘하는 것이란 되게 어려운거 같다.. 연습을 많이 해야할거같다😅
- 글을 정리하면서도 코드의 문제점을 찾아냈다.
완성된 코드라도 하나하나 꼼꼼히 봐야겠단 생각이 들었다.