스크롤 카드 목록 만들기 - WotW

26220 단어 vuewotwwebdevtutorial
이번 주 작은 위젯 시리즈에 오신 것을 환영합니다. 이곳에서 저는 아주 좋은 UI/UX 구성 요소의 GIF나 동영상을 얻고 코드로 그것을 생활 속으로 가져왔습니다.
오늘, 우리는 카드 목록을 만들 것이다. 당신이 아래로 굴러갈 때, 이 카드들은 애니메이션을 나타낼 것이다.이 작은 위젯은 dribble 작성된 Hiwow 의 첫 번째 부분에서 영감을 얻었습니다. 다음과 같습니다.

준비 작업


오늘날의 작은 위젯에 대해 우리는 Vue.js만 사용할 것이며, 애니메이션 라이브러리가 없다는 것은 우리가 Vue의 기능을 대량으로 사용할 것이라는 것을 의미한다.
만약 네가 계속하고 싶다면, 너는 이것codepen template을 갈라놓을 수 있다. 그것은 이미 의존 관계가 있다.

초기 태그


우리의 응용 프로그램이 작동하도록 하기 위해서, 우리는 반드시 주div가 있어야 한다. 그 id는 appwhere Vue이다.js가 설치됩니다.완성된 후에 우리는 카드를 만들기 시작할 수 있습니다. 이 예에서, 나는 단지 한 장만 만들 것입니다. 왜냐하면 잠시 후, 우리는 프로그래밍 방식으로 나머지 카드를 만들 것입니다.
모든 카드에는 내가 카드 내용이라고 부르는 div 옆에 자리 표시자 이미지가 있습니다.이 카드의 내용은 제목, 설명, 등급 평가 데이터를 표시합니다.
<div id="app">
  <div class="card">
    <img class="card__image" src="https://placeimg.com/100/140/animals">      
    <div class="card__content">
      <h3>title</h3>
      <p>description</p>
      <div class="card__rating">
        <span>8.0 </span>
        <span class="card__stars--active">★★★</span>
        <span class="card__stars--inactive">★★</span>
      </div>
    </div>
  </div>
</div>
당신이 이미 알아차렸을 수도 있는 클래스의 이름에 대해 저는 BEM 을 사용하고 있습니다. 이것은 다음 단계에서 카드의 스타일을 설계하는 데 도움이 될 것입니다.

스타일링


지금 우리는 추악한 테스트를 가진 이미지가 하나 있는데, 그것을 바꾸자.초보자에 대해 우리는 옅은 회색 배경을 직접 설정할 것이다body.
body {
  background-color: #FEFEFE;
}
그리고 카드에 대해 우리는 이미지 높이와 일치하는 미리 정의된 높이를 설명할 것이다. 즉, 140px.또한 채우기 설정, 글꼴 변경, 그림자 추가를 통해 세부 사항을 추가하여 부동 카드의 효과를 만듭니다.
.card {
  height: 140px;
  background-color: white;
  padding: 5px;
  margin-bottom: 10px;
  font-family: Helvetica;
  box-shadow: 0px 3px 8px 0px rgba(0,0,0,0.5);
}

우리는 그곳에 도착해서 내부 요소가 스타일 디자인을 할 차례가 되었다.
카드 이미지와 카드 내용은 나란히 표시해야 한다display: inline-block.그림의 너비는 100px 이고 작은 간격으로 텍스트와 분리되기 때문에 카드 내용이 카드 너비의 나머지 부분을 차지할 것이다.
카드 내용의 내부 텍스트는 위쪽과 일치해야 한다. 그렇지 않으면 우리가 원하는 것처럼 보이지 않을 것이다.제목에 대해 h3 요소의 기본 여백이 너무 커서 0 로 설정합니다.
신용카드 등급 평가 용기는 밑부분과 맞춰야 하기 때문에 우리는 position: absolute 을 사용하여 이 점을 실현할 것이다.마지막으로 가장 중요하지 않은 점은 항성span 원소가 서로 다른 색깔을 가지게 된다는 것이다. 이것은 항성이 활동 상태에 있느냐 없느냐에 달려 있다.
.card__img {
  display: inline-block;
  margin-right: 10px;
}

.card__content {
  display: inline-block;
  position: relative;
  vertical-align: top;
  width: calc(100% - 120px);
  height: 140px;
}

.card__content h3 {
  margin: 0;
}

.card__rating {
  position: absolute;
  bottom: 0;
}

.card__stars--active {
  color: #41377C;
}
.card__stars--inactive {
  color: #CCCCCC;
}
그것은 더욱 드리블처럼 보이기 시작해야 한다.

만약 당신이 날카로운 눈을 가지고 있다면, 당신은 활성 항성과 비활성 항성 사이의 공간 차이를 알아차릴 수 있을 것이다.이것은 두 개의 경계 요소 사이의 공간에 의해 발생합니다. 이렇게 하면 삭제할 수 있습니다.
...
      <div class="card__rating">
        <span>8.0 </span>
        <span class="card__stars--active">★★★</span><!-- I'm removing the space
     --><span class="card__stars--inactive">★★</span>
      </div>
...

행위


이제 Vue 인스턴스에서 구성 요소에 사용할 데이터를 설명하기 시작합니다.우리는 많은 카드를 필요로 하지만 나는 한 장을 만들지 않고 세 장을 만들었고 여러 번 복사했다.
const cardsData = [
  {
    img:'https://placeimg.com/100/140/animals',
    title: 'Title 1',
    description: 'Tempora quam ducimus dolor animi magni culpa neque sit distinctio ipsa quos voluptates accusantium possimus earum rerum iure',
    rating: 9.5,
    stars: 4
  },
  {
    img:'https://placeimg.com/100/140/arch',
    title: 'Title 2',
    description: 'Tempora quam ducimus dolor animi magni culpa neque sit distinctio ipsa quos voluptates accusantium possimus earum rerum iure',
    rating: 8.4,
    stars: 5
  },
  {
    img:'https://placeimg.com/100/140/people',
    title: 'Title 3',
    description: 'Tempora quam ducimus dolor animi magni culpa neque sit distinctio ipsa quos voluptates accusantium possimus earum rerum iure',
    rating: 7.234,
    stars: 2
  },
  // copy and paste those three items as many times as you want
]
그리고 저희 Vue 실례에서 이 그룹을 데이터 속성으로 설정하여 추적을 시작할 수 있습니다.
new Vue({
  el: '#app',
  data: {
    cards: cardsData
  }
})
HTML 템플릿으로 데이터를 바인딩합니다.v-for 명령을 사용하면 우리는 카드 데이터 그룹을 교체하고 모든 속성을 나타낼 것입니다.
<div id="app">
  <div class="card" 
    v-for="(card, index) in cards"
    :key="index">

    <img class="card__image" :src="card.img">      
    <div class="card__content">
      <h3>{{card.title}}</h3>
      <p>{{card.description}}</p>
      <div class="card__rating">
        <span>{{card.rating}} </span>
        <span class="card__stars--active">{{card.stars}}</span>
        <span class="card__stars--inactive">{{5 - card.stars}}</span>
      </div>
    </div>

  </div>
</div>
좋아, 우리는 카드가 많아. 불행히도 시청률과 스타는 우리가 예상한 것처럼 보이지 않아.

보시다시피 별의 렌더링은 숫자와 같고, 마지막 등급은 하나 이상의 10진 숫자로 인쇄됩니다.우리는 운이 좋았어, Vue.js는 filters라는 것이 있는데 우리가 원하는 방식으로 모든 데이터를 해석하는 데 도움을 줄 수 있다.
Vue 인스턴스로 돌아가서 두 개의 필터를 선언합니다. 하나는 숫자를 구속하고 다른 하나는 모든 숫자를 별모양으로 변환합니다.
  // ... data
  filters: {
    oneDecimal: function (value) {
      return value.toFixed(1)
    },
    toStars: function (value) {
      let result = ''
      while(result.length < value) {
        result+='' 
      }
      return result
    }
  },
  // ... 
이러한 필터가 준비되면 템플릿으로 돌아가 필터가 필요한 데이터에 추가할 수 있습니다.
  <!-- ... card markup -->
  <span>{{card.rating | oneDecimal}} </span>
  <span class="card__stars--active">{{card.stars | toStars }}</span><!--
  --><span class="card__stars--inactive">{{5 - card.stars | toStars}}</span>
이렇게 간단하다{{ value | filter }}, 데이터는 렌더링 전에 변환될 것이다.

구르다


지금까지, 우리는 카드 목록에 어떤 행위도 추가하지 않았습니다. 우리는 단지 그것의 외관과 렌더링에 관심을 가지고 있을 뿐입니다.애니메이션을 만들 때가 됐어요!
우선, 우리는 응용 프로그램이 스크롤할 때 어떤 방식으로 추적을 시작해야 하며, 이를 위해 사용자 정의 명령이라고 하는 또 다른 Vue 기능을 사용할 것이다.
이 스크롤 명령은 Vue.js docs 에서 추출한 것으로, JS에 추가할 때 v-scroll 명령을 사용할 수 있습니다.
Vue.directive('scroll', {
  inserted: function (el, binding) {
    let f = function (evt) {
      if (binding.value(evt, el)) {
        window.removeEventListener('scroll', f)
      }
    }
    window.addEventListener('scroll', f)
  }
})
그리고 HTML에서 응용 프로그램 div의 빠른 변경 사항을 사용하면 사용할 수 있습니다.
<div id="app" v-scroll="onScroll">
  <!-- ... rest of the markup -->
이제 스크롤 위치를 추적하기 위해 onScroll 방법을 만들 수 있어야 합니다.
  data: {
    cards: cardsData,
    scrollPosition: 0
  },
  methods: {
    onScroll () {
      this.scrollPosition = window.scrollY
    }
  },
추적scrollPosition 속성에 window.scrollY 속성을 추가했습니다.그러면 Vue가 변경될 때 다시 계산하는 데 도움이 됩니다.

카드 애니메이션 설정


최초의 드리블에서 카드가 화면 꼭대기에 도착하기 시작하면 이런 사라지는 효과가 발생한다.이를 위해, 우리는 매번 scrollPosition 갱신할 때 각 카드의 스타일을 계산해야 한다.
다음 두 가지 방법은 생성 양식의 모든 수학 연산을 완성했다.우선 좀 곤혹스러울 수도 있지만, 최선을 다해 설명하겠습니다.
우선, 우리는 cardHeight 상수를 설정합니다. 이 상수는 충전과 간격을 포함하여 카드의 값을 가지고 있습니다.그리고 카드의 인덱스를 고려하여 우리는 카드 위치를 positionY, 첫 번째0, 두 번째160, 세 번째320로 설정했다.
이후에 우리는 카드가 꼭대기에서 얼마나 가까운지 알아야 한다. 우리는 이렇게 하고 값을 부여한다deltaY.우리는 카드가 화면 꼭대기에 도착했을 때 애니메이션을 제작해야 하기 때문에델타이0보다 작을 때만 관심을 가져야 한다.델타Y가 -160보다 작을 때 화면을 떠났기 때문에 0-160 사이에 끼워 넣겠습니다.
마지막으로, 우리는 dY 값에 따라 하나dissapearingValue, yValue, zValue만 만듭니다.말 그대로 dissapearingValue 카드를 퇴색시키기 때문에 css 불투명 속성에 연결합니다.다른 두 개의 값은 카드를 다른 카드 뒤에 있는 것처럼 보일 수 있도록 속성을 바꾸는 데 도움이 될 것이다.
  // ... methods
    calculateCardStyle (card, index) {
      const cardHeight = 160 // height + padding + margin

      const positionY = index * cardHeight
      const deltaY = positionY - this.scrollPosition

      // constrain deltaY between -160 and 0
      const dY = this.clamp(deltaY, -cardHeight, 0)

      const dissapearingValue = (dY / cardHeight) + 1
      const zValue = dY / cardHeight * 50
      const yValue = dY / cardHeight * -20

      card.style = {
        opacity: dissapearingValue,
        transform: `perspective(200px) translate3d(0,${yValue}px, ${zValue}px)`
      }
      return card
    },
    clamp (value, min, max) {
      return Math.min(Math.max(min, value), max)
    }
이제 각 카드를 이 방법에 전달하고 그 결과를 styledCards라는 계산 속성으로 공개합니다.
  computed: {
    styledCards () {
      return this.cards.map(this.calculateCardStyle)
    }
  },
이제 얼마 남지 않았습니다. 새로 만든 스타일을 카드 HTML 코드에 연결합니다.
  <div class="card" 
    v-for="(card, index) in styledCards"
    :style="card.style"
    :key="index">
이제 최종 결과입니다. (아래로 스크롤하는 것을 잊지 마십시오.)
이것이 바로 이번 주의 작은 부품이다.
자세한 내용을 보려면 다른 WotW를 참조하십시오.



  • 또한 다음 주 특정 위젯을 보려면 설명 섹션에 게시하십시오.

    좋은 웹페이지 즐겨찾기