Shenglian / -WORK_TIP

工作上小技巧
4 stars 1 forks source link

[vue] [sliderShow] #23

Open Shenglian opened 6 years ago

Shenglian commented 6 years ago
<template>
  <!-- @wheel="onWheel"-->
  <div class="slider"
    @mouseover="clearTimerEvent"
    @mouseleave="addTimerEvent"
    @touchstart="onTouchStart"
    @mousedown="onTouchStart">
    <div class="slider_list" :style="setStyle" @transitionend="onTransitionEnd">
      <div class="slider_item" v-for="(arr, index) in cloneSliderArr" :key="index" :style="{ backgroundImage: `url(${arr.img})` }"></div>
    </div>

    <div class="slider_pagination">
      <div class="slider_pagination_bullet" :class="{active: index + 1 === computeIndex}" 
      v-for="(arr, index) in bullets" :key="index"
      @click="goTo(index + 1)"></div>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'slider',
    props: {
      seconds: {
        type: Number,
        default: 3000,
      },
      speed: {
        type: Number,
        default: 500,
      },
    },
    data() {
      return {
        sliderArr: [{
          img: 'https://images.unsplash.com/photo-1494005199821-2cb74a8e75fb?auto=format&fit=crop&w=1950&q=60&ixid=dW5zcGxhc2guY29tOzs7Ozs%3D',
        },
        {
          img: 'https://images.unsplash.com/photo-1495206255513-257bdf652e26?auto=format&fit=crop&w=2090&q=60&ixid=dW5zcGxhc2guY29tOzs7Ozs%3D',
        },
        {
          img: 'https://images.unsplash.com/photo-1507706132643-4b3dabbca8b3?auto=format&fit=crop&w=2134&q=60&ixid=dW5zcGxhc2guY29tOzs7Ozs%3D',
        }],

        isLoop: true,          // 增加前後 
        startTime: null,
        clientWidth: 0,
        currentPage: 1,
        translateX: 0,
        startPos: null,
        startTranslate: 0,
        transitionDuration: 0,
        delta: 0,

        timer: null,
      };
    },
    watch: {},
    mounted() {
      this.slideInit();
    },
    computed: {
      computeIndex() {
        let index = 0;

        console.log('this.currentPage: ', this.currentPage);
        if (this.currentPage === 1 || this.currentPage === this.slides.length - 1) {
          index = 1;
        } else if (this.currentPage === this.slides.length - 2 || this.currentPage === 0) {
          index = this.slides.length - 2;
        } else {
          index = this.currentPage;
        }

        return index;
      },
      bullets() {
        let computeBullets = 0;

        if (this.isLoop) {
          computeBullets = this.sliderArr.length - 2;
        } else {
          computeBullets = this.sliderArr.length;
        }

        return computeBullets;
      },
      cloneSliderArr() {
        const sliderArrFirst = this.sliderArr[0];
        const sliderArrLast = this.sliderArr[this.sliderArr.length - 1];

        this.sliderArr.push(sliderArrFirst);
        this.sliderArr.unshift(sliderArrLast);

        return this.sliderArr;
      },
      setStyle() {
        return {
          transform: `translate3d(${this.translateX}px, 0px, 0px)`,
          transitionDuration: `${this.transitionDuration}ms`,
        };
      },
    },
    methods: {
      slideInit() {
        this.$nextTick(() => {
          this.getSlideList();
          this.getClientWidth();
          this.move(this.currentPage);
        });
      },

      getSlideList() {
        this.slides = this.$el.querySelectorAll('.slider .slider_item');
        this.setTimer();
      },
      getClientWidth() {
        this.clientWidth = this.slides ? this.slides[0].clientWidth : null;
      },

      clearTimerEvent() {
        this.removeTimer();
      },
      addTimerEvent() {
        this.setTimer();
      },

      setTimer() {
        this.timer = setInterval(this.setTimerNext, this.seconds);
      },
      removeTimer() {
        clearInterval(this.timer);
      },

      setTimerNext() {
        this.transitionDuration = 500;
        this.currentPage = this.currentPage + 1;
        this.move(this.currentPage);
      },

      onTransitionEnd() {
        if (this.timer) {
          if (this.currentPage === this.slides.length - 1) {
            this.transitionDuration = 0;
            this.currentPage = 1;
            this.move(this.currentPage);
          }
        }
      },

      next() {
        if (this.currentPage < this.slides.length - 1) this.currentPage = this.currentPage + 1;
        this.move(this.currentPage);
      },
      prev() {
        if (this.currentPage > 0) this.currentPage = this.currentPage - 1;
        this.move(this.currentPage);
      },
      goTo(index) {
        this.currentPage = index;
        this.move(index);
      },
      move(index) {
        this.translateX = -(index * this.clientWidth);
        this.startTranslate = this.translateX;
      },

      setTranslate(value) {
        this.translateX = value;
      },
      getTranslate() {
        return this.translateX;
      },

      getTouchPos(e) {
        const key = 'pageX';
        return e.changedTouches ? e.changedTouches[0][key] : e[key];
      },
      onTouchStart(e) {
        if (this.timer) {
          this.removeTimer();
        }

        this.startPos = this.getTouchPos(e);
        this.startTime = new Date().getTime();
        this.transitionDuration = 0;

        // 4
        if (this.currentPage === this.slides.length - 1) {
          this.currentPage = 1;
          this.startTranslate = -(this.currentPage * this.clientWidth);
        // 0
        } else if (this.currentPage === 0) {
          this.currentPage = this.slides.length - 2;
          this.startTranslate = -(this.currentPage * this.clientWidth);
        }

        document.addEventListener('touchmove', this.onTouchMove, false);
        document.addEventListener('touchend', this.onTouchEnd, false);
        document.addEventListener('mousemove', this.onTouchMove, false);
        document.addEventListener('mouseup', this.onTouchEnd, false);
      },
      onTouchMove(e) {
        this.delta = this.getTouchPos(e) - this.startPos;

        this.setTranslate(this.startTranslate + this.delta);
      },

      onTouchEnd() {
        if (!this.timer) {
          this.setTimer();
        }

        const isQuickAction = new Date().getTime() - this.startTime < 1000;

        this.transitionDuration = this.speed;

        if (this.delta < -100 || (isQuickAction && this.delta < -15)) {
          this.next();
        } else if (this.delta > 100 || (isQuickAction && this.delta > 15)) {
          this.prev();
        }

        document.removeEventListener('touchmove', this.onTouchMove);
        document.removeEventListener('touchend', this.onTouchEnd);
        document.removeEventListener('mousemove', this.onTouchMove);
        document.removeEventListener('mouseup', this.onTouchEnd);
      },
      onWheel(e) {
        if (e.deltaY > 0) {
          this.next();
        } else {
          this.prev();
        }
      },
    },
  };
</script>

<style lang="scss">
.slider {
  margin-top: 100px;
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.slider .slider_list {
  display: flex;
  width: 100%;
  height: 200px;
  transition: all 0ms ease;
}

.slider .slider_list .slider_item {
  width: 100%;
  height: 100%;
  background: #333;
  background-size: cover;
  background-origin: center;

  display: flex;
  flex-shrink: 0;

  justify-content: center;
  align-items: center;
  text-align: center;
  font-size: 48px;
  color: #fff;
}

.slider .slider_pagination {
  margin-top: 10px;
  display: flex;
  justify-content: center;
}

.slider .slider_pagination .slider_pagination_bullet {
  margin: 0 3px;
  width: 10px;
  height: 10px;
  border: 1px solid #dddddd;
  background: #dddddd;
  border-radius: 100%;
  &.active {
    background: #ffffff;
  }
}
</style>
Shenglian commented 6 years ago

Demo SlideShow

Shenglian commented 6 years ago

TODO: