[Vue] 무한 루프 슬라이드

Simple Key·2021년 3월 31일
0

Vue로 프로젝트를 하면서 무한 슬라이드 만들기

❓ 내가 말하는 무한 슬라이드란 ?

  • 위 영상처럼 왼쪽이든 오른쪽이든 계속 넘길 수 있는 슬라이드
  • 1 → 2 → 3 → 4 → 5 → 1 ... 순으로 오른쪽으로 계속 넘기면 마지막장 다음에 다시 1부터 시작되어야 한다.
  • 반대로 왼쪽으로 계속 넘기면 역순으로 계속 반복되어야 한다. (ex. 5 → 4 → 3 → 2 → 1 → 5 → 1...)

결과물:

이 영상의 슬라이드는 mounted에서 setInterval을 설정하여 자동으로 오른쪽 슬라이딩이 되게 해놨다.

Vue로 코딩을 하였기때문에 v-for로 각 슬라이드 아이템을 생성

// template
<template>
  //..나머지 코드 중략
  <div class="slide-container">
    <button @click="moveSlideToLeft">
      <img src="왼쪽버튼이미지입니다." />
    </button>
   <div class="slide-window">
      <div class="slide" 
           :class="{ slide-active': transitionOn }" 
           :style="{transform: 'translate3d(' + slideCoord + 'px, 0, 0)',}">
        <SlideCard v-for="card in cardArray" :key="card.name" /></div>
      </div>
    </div>

    <button @click="moveSlideToRight">
      <img src="오른쪽버튼이미지입니다."/>
    </button>
  </div>
</template>
// script
<script>
  //..코드 중략
export default {
  data(){
    transitionOn: true; //슬라이드가 움직일때 트렌지션을 줄 것인지
    cardArray : [], // 슬라이드 카드가 담길 배열 mounted에서 담아준다.
    slideCoord: -300, // 옆으로 움직일 값, (슬라이드의 마진,패딩값 포함된 width)
    // 이 값으로 슬라이드 카드를 담고있는 .slide의 css에 transform: translate3d(여기, 0 , 0) 에 넣어줘야 한다.
  }
}
</script>

//..style 생략

😈 문제 발생
처음엔 슬라이드 카드 배열안의 카드 순서만 바꾸는 방법을 적용했다가 문제를 겪었다.
배열의 맨 앞을 잘라내서 뒤에 갖다 붙이는 방법으로 배열 내 순서를 바꿨다. 하지만......
이 방법으로는 .slide는 계속 오른쪽으로 이동하는데 배열안의 카드의 순서만 바뀔 뿐 배열의 길이는 그대로였기때문에 카드들을 담고 있는 슬라이드에 빈 칸이 표시되는 문제 발생.

비유하자면 기차에서 1,2,3,4,5 사람이 순서대로 자리만 바꿨을뿐 기차는 계속해서 앞으로 이동했기때문에
기차가 1,2,3,4,5의 사람들을 볼 수 없게된다.

🤓 문제 해결하기
배열의 앞을 잘라내지않고 뒤에 계속 붙여나가는 방법을 사용, 하지만 이 방법은 배열의 길이가 무한으로 늘어나는 문제가 있다.
배열이 늘어남에따라 v-for로 생성대는 컴포넌트 역시 무한으로 늘어나게 된다.
때문에 배열이 한 번 순환하면 늘어난 배열을 다시 초기 배열의 값으로 바꿔주었다.
(예. [1,2,3,4,5] → [1,2,3,4,5,1] → [1,2,3,4,5,1,2...5] → [1,2,3,4,5])

다만 이 방법도 그닥 좋다고 생각들지 않았다.
배열 뒤로 카드를 붙여나가는 방법으로 datacurrentIdx라는 값을 만들어 놓고, 오른쪽버튼 클릭이벤트를 발생시킬때마다 currentIdx라는 값에 +1을 더한다.
슬라이드카드배열.splice(슬라이드카드배열의 마지막 인덱스, 0, 카드 초기배열[currentIdx]) 으로 배열의 길이를 늘려나갔다보니 datacurrentIdx값과 카드 초기배열 값을 저장해두었다.
배열의 한 사이클을 돌면 슬라이드 카드 배열초기 배열 값과 동일하게 바꿔주고 currentIdx는 다시 0으로 만들어 주는 방법..

난 배열의 길이를 조작하지 않고 순서만 바꾸면서 슬라이드되는 효과를 만들고 싶었다.

그래서 생각해낸 방법이 슬라이드 트렌지션이 발생한 후 다음 슬라이드를 넘기기 전에 보여지고 있는 순서로 배열 순서를 만들어주는 방법이다.

methods: {
  resetCardArrayToRight() {
    // 슬라이드 카드 배열 끝에 맨 앞에 있던 카드를 추가
    this.cardArray.splice(this.cardArray.length, 0, this.cardArray[0]);
    
    // 맨 끝에 추가한 후 맨 앞에 있던 카드는 삭제
    this.cardArray.splice(0, 1);
    
    // 잠시 transition 을 off 하기
    this.transitionOn = false;
    
    // slideCoord를 초기값으로 설정
    this.slideCoord = -300;
},
    
  // 슬라이드 오른쪽 버튼 클릭이벤트 @click=" moveSlideToRight"
  moveSlideToRight() {
    // -300 씩 이동
    this.slideCoord = this.slideCoord - 300
    
    // transitionOn은 true로 
    this.transitionOn = true
    
    // 0.5초 뒤에 배열의 순서를 바꾸고 slideCoord값을 다시 초기 값으로 설정
    // 이때만 transition을 off하여 움직이지 않는 것 처럼 눈속임한다.
    // 여기 setTimeout의 delay 시간은 css의 transition의 duration과 같게 설정해야한다.
    setTimeout(this.resetCardArrayToRight, 500)
    },
}

왼쪽으로 이동하는 방법도 오른쪽과 같다. 다만 처음 슬라이드가 시작할 때 인덱스 0이 아닌 1부터 보여줘야했다. 이 때문에 slideCoord의 초기 값을 0이 아닌 슬라이드 하나 넘어간 -300으로 설정했다.
0부터 시작한다면 처음에 왼쪽으로 넘길때 왼쪽에 왼쪽에 카드가 없어서 빈칸이 넘어오게 되기 때문..

위 방법으로 currentIdx나 초기 배열의 값을 쓸데없이 data에 저장하지 않아도 된다.

tip 참고로 처음엔 .slide-container에 relative, .slide에 absoluteleft값을 더하거나 빼는 방법으로 슬라이드를 좌우 이동하였으나, transform: translate3d를 사용하는 방법을 추천한다고 한다.

profile
프론트엔드 개발자 심기현 입니다.

1개의 댓글

comment-user-thumbnail
2021년 8월 17일

작동이 되지 않습니다ㅠㅠ 혹시 완성된 코드를 참고할 수 있을까요?

답글 달기