Vue 및 GSAP 애니메이션 카드 슬라이더 - WotW

27345 단어 vuewotwwebdevtutorial
이것은 이번 주 소부품 시리즈의 세 번째 부분이다.
오늘은 Vue를 사용하여 처음부터 스타일 카드 슬라이더를 만드는 과정을 보여 드리겠습니다.
이 작은 부품의 영감은 this입니다. 보기에 이렇습니다.

준비 작업


오늘날의 작은 위젯과 유사하게 우리는 vue.js을 사용하여 상호작용을 하고 tweenlite을 사용하여 애니메이션을 진행할 것이다.

HTML 구조


기본적으로 슬라이더의 요소는 카드와 정보 용기입니다. 다음 단계에서 스타일을 설정할 수 있도록 먼저 종류와 종류를 추가합니다.
<div id="slider" class="slider">
  <div class="slider-cards">
    <div class="slider-card"></div>
    <div class="slider-card"></div>
    <div class="slider-card"></div>
  </div>
  <div class="slider-info">
    <h1>Title</h1>
    <p>description</p>
    <button>Action</button>
  </div>
</div>

스타일링!


현재 그것은 최종 제품과 결코 가까워 보이지 않는다.먼저 다음 규칙을 사용하여 뷰포트 이동을 시뮬레이션합니다.
.slider {
  overflow: hidden;
  background-color: #1F1140;
  width: 360px;
  height: 640px;
}
카드에 대해 나는 용기의 간격을 사용하여 첫 번째 카드를 가운데에 놓고 이 카드들은 오른쪽 간격으로 서로 분리할 것이다.그 밖에 우리는 카드 용기가 상대적이고 z 인덱스가 slider-infodiv의 맨 위에 있어야 한다.
카드는 inline이어야 한다. 이렇게 하면 서로 한쪽에 놓을 수 있지만, 이 작업에 있어서 용기는 충분히 넓어야 한다.이런 상황에서 카드 한 장의 너비는 약 300px이기 때문에 용기의 너비는 900px가 될 것이다. 왜냐하면 우리는 세 장의 카드가 있기 때문이다. (만약 우리가 더 많은 카드를 가지고 있다면 필요한 총 너비를 계산해야 한다.)
마지막으로, 우리는 카드가 움직이는 인상을 남기기 위해 네모난 테두리 그림자를 추가할 것이다.
.slider-cards {
  position: relative;
  width: 900px;
  margin: 20px 50px;  
  z-index: 1;
}
.slider-card {
  display: inline-block;
  background-color: grey;
  overflow: hidden;
  width: 260px;
  height: 360px;
  margin-right: 30px;
  border-radius: 12px;
  box-shadow:0px 60px 20px -20px rgba(0, 0, 0, 0.3)
}
저희가 점점 가까워지고 있어요.

이제 slider-info으로 개조할 차례입니다.정보를 가운데에 표시하기 위해 배경색, 치수 및 여백을 추가합니다.
중요한 것은 카드 용기와 중첩된다는 점이다. 이를 위해 margin-top은 마이너스이며, 보상을 위해 padding-top을 추가했다.
아래쪽 단추가 정보 용기와 같은 원각을 가지도록 overflow 속성을 숨겨야 합니다.그런 다음 제목, 설명 및 버튼 스타일을 다음과 같이 설정합니다.
.slider-info {
  position: relative;
  overflow: hidden;
  background-color: white;
  margin-top: -200px;
  margin-left: 30px;
  padding: 200px 20px 0;
  width: 260px;
  height: 200px;
  text-align: center;
  border-radius: 8px;
}
.slider-info h1 {
  font-family: Arial Black, Gadget, sans-serif;
  line-height: 25px;
  font-size: 23px;
}
.slider-info p {
  font-family: Arial, Helvetica, sans-serif;
}
.slider-button {
  position: absolute;
  width: 100%;
  height: 50px;
  bottom: 0;
  left: 0;
  border: none;
  color: white;
  background-color: #E71284;
  font-size: 18px;
  font-family: Arial, Helvetica, sans-serif;
}

많이 좋아졌어요.

데이터 채우기


Vue를 사용할 준비가 되었으므로 인스턴스를 만들고 The Movie DB에서 데이터를 설정합니다.
new Vue({
  el: '#slider',
  data: {
    slides: [
      {
        title: 'Ready Player One',
        description: 'When the creator of a popular video game system dies, a virtual contest is created to compete for his fortune.',
        image: 'https://image.tmdb.org/t/p/w300_and_h450_bestv2/pU1ULUq8D3iRxl1fdX2lZIzdHuI.jpg'
      },
      {
        title: 'Avengers: Infinity War',
        description: 'As the Avengers and their allies have continued to protect the world from threats too large for any...',
        image: 'https://image.tmdb.org/t/p/w300_and_h450_bestv2/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg'
      },
      {
        title: 'Coco',
        description: 'Despite his family’s baffling generations-old ban on music, Miguel dreams of becoming an accomplished musician...',
        image: 'https://image.tmdb.org/t/p/w300_and_h450_bestv2/eKi8dIrr8voobbaGzDpe8w0PVbC.jpg'
      }
    ]
  }
})
현재 데이터를 표시할 수 있도록 기본 선택 영화를 정의해야 합니다.이것은 데이터의 또 다른 변수 selectedIndex과 계산 속성을 통해 실현할 수 있으며, 이 속성은 선택한 색인에 따라 슬라이드의 데이터를 제공할 수 있다.
  data: {
    // ... slide data
    selectedIndex: 0
  },
  computed: {
    selectedSlide () {
      return this.slides[this.selectedIndex]
    }
  }
그리고 우리의 템플릿에서 우리는 v-for으로 카드를 귀속시키고 정보를 해당하는 데이터에 귀속시킬 것이다.
<div id="slider" class="slider">
  <div class="slider-cards">
    <div 
         v-for="(slide, index) in slides" 
         :key="index"
         class="slider-card">
      <img :src="slide.image" :alt="slide.title">
    </div>
  </div>
  <div class="slider-info">
    <h1>{{selectedSlide.title}}</h1>
    <p>{{selectedSlide.description}}</p>
    <button class="slider-button">BOOK</button>
  </div>
</div>

이것은 보기에 거의 완성된 것 같다. 적어도 미학적으로는 그렇지만, 우리는 여전히 필요하다.

상호작용


만약 우리가 슬라이더의 상호작용을 분해한다면, 그것들은 기본적으로 3이다. 우리가 카드를 누르고 카드를 이동하며 카드를 놓을 때.이러한 작업을 추적하기 위해서는 @mouseDown, @mouseUp, @mouseMove을 Vue 인스턴스에 연결하는 방법이 필요합니다.또한 이미지의 재촬영을 방지하기 위해 draggable=false 속성을 가지고 있어야 합니다.
<div id="slider" class="slider" @mouseMove="mouseMoving">
  <div class="slider-cards">
    <div @mouseDown="startDrag"
         @mouseUp="stopDrag"
         v-for="(slide, index) in slides" 
         :key="index"
         class="slider-card">
      <img :src="slide.image" :alt="slide.title" draggable="false">
    </div>
  </div>
  <!-- slider info and the rest -->
이제 Vue 쪽에서 이 메서드를 작성하고 데이터 객체에 몇 가지 변수를 추가해야 합니다.
  data: {
    // ... other variables
    dragging: false,
    initialMouseX: 0,
    initialCardsX: 0,
    cardsX: 0
  },
  methods: {
    startDrag (e) {

    },
    stopDrag () {

    },
    mouseMoving (e) {

    }
  }
이 세 가지 방법은 모두 하나의 사건을 받을 수 있지만, 우리는 estartDrag의 방법에서만 그것을 사용할 수 있다.
다음 코드 세션에서, 나는 이 세 가지 방법을 채우기 위해 한 걸음 한 걸음 과정을 분해할 것이다. 따라서 나는 나머지 코드를 무시할 것이다.
우선, 우리는 마우스 동작에 따라 mouseMoving을 true 또는 false로 설정해야 한다.
startDrag (e) {
  this.dragging = true
},
stopDrag () {
  this.dragging = false
},
mouseMoving (e) {

}
매우 간단합니다. 이제 카드를 드래그할 때만 카드를 이동할 수 있기를 바랍니다. 따라서 dragging 방법에 다음과 같은 조건을 추가합니다.
startDrag (e) {
  this.dragging = true
},
stopDrag () {
  this.dragging = false
},
mouseMoving (e) {
  if(this.dragging) {

  }
}
자, 이제 재미있어집니다. 카드와 마우스의 위치를 추적해야 합니다. 드래그를 시작할 때 mouseMoving 속성은 마우스의 위치를 알려 줍니다. 저희 데이터의 pageX은 카드의 용기 위치를 추적합니다.
startDrag (e) {
  this.dragging = true
  this.initialMouseX = e.pageX
  this.initialCardsX = this.cardsX
},
stopDrag () {
  this.dragging = false
},
mouseMoving (e) {
  if(this.dragging) {

  }
}
메모리 카드와 마우스의 초기 X를 저장한 후 cardsX 방법으로 다음과 같은 작업을 수행할 때 우리는 마우스 위치 차이를 계산하여 카드 용기의 목표 위치를 제거할 수 있다.
startDrag (e) {
  this.dragging = true
  this.initialMouseX = e.pageX
  this.initialCardsX = this.cardsX
},
stopDrag () {
  this.dragging = false
},
mouseMoving (e) {
  if(this.dragging) {
    const dragAmount = e.pageX - this.initialMouseX
    const targetX = this.initialCardsX + dragAmount
    this.cardsX = targetX
  }
}
우리 구성 요소는 거의 이동할 수 있습니다. 카드 용기를 mouseMoving 속성에 연결하는 방법을 찾으면 이 속성을 HTML에 추가하여 완성할 수 있습니다.
...
<div class="slider-cards" :style="`transform: translate3d(${cardsX}px,0,0)`">
...
"왜 일반적인 2d 번역이 아니라translate3d를 사용해야 합니까?"라고 물어볼 수도 있습니다.cardsX은 하드웨어가 가속화되어 대부분의 경우 더 좋은 성능을 가지기 때문이다.전화는 this site입니다.
슬라이드는 현재 이동하고 있지만 작은 문제가 하나 있습니다. 슬라이드를 내려놓을 때, 슬라이드는 우리가 내려놓은 곳에 머무르고, 영화 정보도 변하지 않습니다.우리가 진정으로 필요로 하는 것은 그들이 가장 가까운 슬라이드를 찾아서 중간에 놓는 것이다.
최근의 슬라이드를 찾기 위해서, 우리는 현재 위치를 카드의 너비로 나누고, 그 결과를 반올림하기만 하면 된다.그리고 TweenLite를 사용하면 카드를 해당 위치로 애니메이션화합니다.
stopDrag () {
  this.dragging = false

  const cardWidth = 290
  const nearestSlide = -Math.round(this.cardsX / cardWidth)
  this.selectedIndex = Math.min(Math.max(0, nearestSlide), this.slides.length -1)
  TweenLite.to(this, 0.3, {cardsX: -this.selectedIndex * cardWidth})
}
이 공식을 더욱 잘 이해하기 위해 이gif는 translate3d값과 cardsX의 관련성을 나타냈다.

이제 최종 결과!
현재 데스크톱 장치에서만 작동하지만 nearestSlide에서 복구될 수 있습니다. this article에서 더 많은 정보를 얻을 수 있습니다.
이것은 이번 주의 세 번째 작은 부품이다.
지난번 검사 안 하셨으면
또한 다음 주 특정 위젯을 보려면 설명 섹션에 게시하십시오.

좋은 웹페이지 즐겨찾기