Slider Transition

by dhwanilshah

HTML

<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="app">
  <transition-group tag="div" :name="directionClass" class="scrollable-content">
    <div v-for="(card, index) in cards" :key="card['id']" class="card-slider" :id="card['id']">
      Card - {{ card['id']}}
    </div>
  </transition-group>
  <br>
  {{ activeCardIDs }}
  <button  @click="swipeCard('left')">Left</button>
  <button @click="swipeCard('right')">Right</button>
</div>

CSS

button {


}

.fade-enter-active,
.fade-leave-active {
  transition: opacity .5s
}

.fade-enter,
.fade-leave-active {
  opacity: 0
}

.scrollable-content {
  max-width: 50%;
  width: 50%;
  min-width: 50%;
  background-color: red;
  position: relative;
  display: flex;
  padding: 10px 0;
  margin-left: 25%;
}

.card-slider {
  min-width: 33%;
  color: white;
  width: 50% !important;
  display: inline-block;
  padding: 5px 0;
  text-align: center;
}

.card-slider:nth-child(odd) {
  background-color: blue;
}
.card-slider:nth-child(even) {
  background-color: lightblue;
}

.swipe-left-enter-active,
.swipe-left-leave-active,
.swipe-right-enter-active,
.swipe-right-leave-active {
  transition: all 5s ease-in-out;
}

  .swipe-right-enter-to {
    transform: translateX(-300%);
  }

  .swipe-right-leave-to {
    transform: translateX(-300%);
}

.swipe-left-enter-to {
  background-color: grey;
  transform: translateX(-488px);
}

.swipe-left-leave-to {
  background-color: yellow;
  transform: translateX(-488px);
}

Vue

new Vue({
  el: '#app',
  data: {
    n: 0,
    activeCardIDs: null,
    activeCardIndex: 0,
    cards: [],
    swipeDirection: null,
    scrollerConfig: {'cardsInView': 3},
    cardsList: [{'id': 1}, {'id': 2}, {'id': 3}, {'id': 4}, {'id': 5}]
  },
  beforeMount: function () {
    console.log('Setting Up Cards: ', this)
    this.setUpCards(this.cards)
  },
  computed: {
    directionClass: function () {
      return {
        'left': 'swipe-left',
        'right': 'swipe-right'
      }[this.swipeDirection]
    },
    cardCount: function () {
      return this.cardsList.length
    },
  },
  methods: {
    setUpCards: function (cards) {
      this.activeCardIndex = 0
      this.$nextTick(() => {
        if (this.cardCount >= 1) {
          this.makeCardsActive(this.activeCardIndex)
        } else {
          this.cards = []
        }
      })
    },
    swipeCard: function (direction) {
      this.swipeDirection = direction
      if (this.cardCount > this.scrollerConfig['cardsInView']) {
        this.swipeDirection = direction
        let cardsInView = this.scrollerConfig['cardsInView']
        if (direction === 'left') {
          if (this.activeCardIndex - cardsInView < 0) {
            // if activeIndex goes into negative, then we need to wrap it, add the negative offset i.e. wrapped from end
            let negativeOffset = this.activeCardIndex - cardsInView
            this.activeCardIndex = this.cardCount - cardsInView < 0 ? 0 : this.cardCount + negativeOffset
          } else {
            // else, just subtract the number of cards we have to show
            this.activeCardIndex = this.activeCardIndex - cardsInView
          }
        } else if (direction === 'right') {
          this.activeCardIndex = (this.activeCardIndex + cardsInView) % this.cardCount
        }
        this.makeCardsActive(this.activeCardIndex)
      }
    },
    makeCardsActive: function (startIndex) {
      this.cards = null
      this.activeCardIDs = null
      this.$nextTick(() =>...