Mobile terminal multicast component is a very wide range of components, the purpose of the implementation of this reusable multicast component is to strengthen their understanding of VUE and CSS through continuous practice

  • The following functions should be realized by the components of the multicast chart
1. Can realize automatic playback, and increase the playing animation 2. Can freely control the playing animation time 3. 4. The parent component can listen to the index value of the rotation chart when switching 5. Can control the initial position index value of the rotation chart 6. Can customize the color of the indicatorCopy the code

👇 to see the effect of the implementation (when the rotation map can listen to the change of the index value)

1. The first thing that comes to mind is that several images are arranged horizontally, and when 100% of the parent element is filled, the rest is hidden. The index value is obtained by calculating the total number of pictures obtained in the rotation chart, and the total width is 3. We control the autoplay by adding a loop timer, using transform: translateX() to offset the horizontal and then calculating the property to change the offset distance.Copy the code

👇 see how it works (swipe. Vue)

    <template>
      <div class="swiper" ref="swiper" @click.prevent="handleClick">
        <div 
          class="swiper-list" 
          :style="{width: swiperListWidth + 'px', transform: 'translateX(' + translateX + 'px)', transitionDuration: transitionDuration + 's' }" 
          ref="swiperList"
        >
          <slot></slot>
        </div>
        <div class="dot">
          <span 
            v-for="(x, i) in sum" :key="'dot' + x" 
            :style="{background: i === index ? indicatorColor : 'rgba(255, 255, 255, .5)'}" 
            :class="[i === index ? 'on': '']"
          >
          </span>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      name: 'v-swipe'.data () {
        return {
          swiperWidth: ' 'InitialIndex, // Sum: 0, // transitionDuration: 0.5, //' '// timer startX:' ', // touchstart offset:' ', // move offset value Loop: 0}}, props: {duration: {type: Number,
          default: 3000
        },
        initialIndex: {
          type: Number,
          default: 0
        },
        indicatorColor: {
          type: String,
          default: '#fff'}}, computed: {// The width of the rotation graph listswiperListWidth () {
          returnThis. swiperWidth * this.sum}, // The list offset of the rotation maptranslateX () {
          return this.index * this.swiperWidth * -1
        }
      },
      created () {
        this.$nextTick(() = > {let swiper = this.$refsSwiper // Get the number of images in the rotation chartlet swiperItems = document.querySelectorAll('.swiper-item') this.sum = swiperItems. Length This. SwiperWidth = swiper.offsetwidth this.autoplay () // addEventListener cannot use anonymous functions, Unable to unbind swiper.addeventListener ('touchstart', this.touchStart)
          swiper.addEventListener('touchmove', this.touchMove)
          swiper.addEventListener('touchend', this.touchEnd)
        })
      },
      methods: {
        autoPlay () {
          this.timer = setInterval(() => {
            letIndex = this.index + 1 // 0%5=0, 1%5=1, 5%5=0ifThis. index = index % this.sum this.$emit('change', this.index) }, this.duration) }, TouchStart (e) {clearInterval(this.timer) this.TransitionDuration = 0 this.startx = e.targetTouches[0].clientX }, touchMove (e) { this.offset = this.startX - e.targetTouches[0].clientX this.$refs.swiperList.style.transform = `translateX(${this.translateX - this.offset}px)`
        },
        touchEnd() {this.transitionDuration = 0.5 // Calculate the offset and round it up. If the drag distance is greater than or equal to 0.5, change the rotation chartlet num = Math.round(this.offset / this.swiperWidth)
          letSum = this.index + num = this.index + num = this.index + numif (sum > this.sum - 1) {
            sum = 0
          } else if(sum < 0) {sum = this. sum-1} // If the drag distance is less than half, the index value does not change, and the calculation attribute cannot be triggeredif (sum === this.index) {
            this.$refs.swiperList.style.transform = `translateX(${this.translateX}px)`
          } else {
            this.index = sum
            this.$emit('change', this.index)} // When the first gesture slides, Offset = 0 this.autoplay ()}, handleClick (e) {e.preventDefault() this.$emit('click', this.index)}}, // Remove the binding event before instance destructionbeforeDestroy () {
        let swiper = this.$refs.swiper
        swiper.removeEventListener('touchstart', this.touchStart)
        swiper.removeEventListener('touchmove', this.touchMove)
        swiper.removeEventListener('touchend', this.touchEnd)
      }
    }
    </script>
    
    <style lang="less"scoped> .swiper { position: relative; width: 100%; height: 12rem; overflow: hidden; .swiper-list { display: flex; width: 100%; height: 100%; transition-property: all; Transition-timing -function: cubic-bezier(0.18, 0.89, 0.32, 1.28); } .dot { display: flex; position: absolute; width: 100%; margin-top: -15px; justify-content: center; span { @size: 8px; width: @size; height: @size; background-color: rgba(255, 255, 255, .5); border-radius: 50%; margin-left: 5px; } .on { width: 12px; border-radius: 30%; The transition: 0.3 s linear width; } } } </style>Copy the code

👇 see how this is implemented (swipeitem.vue)- use slot to insert content

    <template>
      <div class="swiper-item">
        <slot></slot>
      </div>
    </template>
    
    <script>
    export default {
      name: 'v-swipe-item'
    }
    </script>
    
    <style lang="less" scoped>
      .swiper-item {
          width: 100%;
        }
        img {
          display: block;
          width: 100%;
          height: 100%;
        }
    </style>
Copy the code