前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >vue轮播组件--不插电手动粘贴版

vue轮播组件--不插电手动粘贴版

作者头像
Ganother
发布2019-02-26 10:41:10
8240
发布2019-02-26 10:41:10
举报
文章被收录于专栏:SylvanasClubSylvanasClub

概述

轮播的原理是每一帧都选出一个当前元素,前一个元素,后一个元素然后排成一行,最后改变这三个元素的translate来触发css3的transition进行动画,当有touch事件的时候,要实时改变各个元素的位置,所以要把transition关闭。组件demo地址 m.cm233.com

<template>
  <section class="shuffling-wrapper">
    <ul :class="['shuffling-bar',{trans : open, transnext: openNext, transpre: openPre}]">
      <template v-for="item in shufflingData">
        <li
        :class="['item', {
          pre: $index == preIndex && shufflingData.length > 2,
          next: $index == nextIndex && shufflingData.length > 2,
          current: $index == shufflingIndex}]"
        :style="translateObj[$index]"
        @touchstart="shufflingData.length > 2 && touchStart($event)"
        @touchmove.prevent="shufflingData.length > 2 && touchMove($event)"
        @touchend="shufflingData.length > 2 && touchEnd($event)">
          <a class="link" href="{{item.link}}">
            <img class="img" :src="item.img" alt="{{item.subject}}">
          </a>
        </li>
      </template>
      <li class="shuffling-btn">
        <i class="btn-item" :style="{width: btnWidth+'px', transform: 'translate3d('+(shufflingIndex*100)+'%,0,0)'}"></i>
      </li>
    </ul>
  </section>
</template>
   .shuffling-wrapper{
    width: 100%;
  }
  .shuffling-bar{
    position: relative;
    width: 100%;
    overflow: hidden;
    padding-top: 70.66%;
    .item{
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      margin: auto;
      z-index: 100;
      user-select: none;
      -webkit-touch-callout:none;
      -webkit-tap-highlight-color: transparent;
    }
    .link{
      display: block;
      width: 100%;
      height: 100%;
    }
    .img{
      display: block;
      width: 100%;
      height: 100%;
    }

    .current{
      transform: translate3d(0, 0, 0);
      z-index: 300;
    }
    .pre{
      transform: translate3d(-100%, 0, 0);
      z-index: 300;
    }
    .next{
      transform: translate3d(100%, 0, 0);
      z-index: 300;
    }
  }
  .trans{
    .current{
        transition: transform .3s ease-in-out;
    }
  }
  .transpre{
    .pre{
        transition: transform .3s ease-in-out;
    }
  }
  .transnext{
    .next{
        transition: transform .3s ease-in-out;
    }
  }
  .shuffling-btn{
    height: 3px;
    background-color: rgba(255,255,255,.8);
    position: relative;
    z-index: 400;
    .btn-item{
      position: absolute;
      top: 0;
      left: 0;
      height: 3px;
      background-color: #e81926;
      border-radius: 1px;
      transition: transform .3s ease-in-out;
    }
  }
import {getClient} from '../vuex/getters'
  export default{
    ready: function(){ //初始化
      this.caculateIndex(); //计算初始前一个元素,当前元素,后一个元素
      this.autoScroll(); //开始自动轮播

    },
    props: {
      shufflingData: {
        type: Array,
        default: () => []
      }
    },
    data(){
      let that = this;
      return {
        shufflingIndex: 0, //当前元素的index
        nextIndex: 0, //后一个元素的序列
        preIndex: 0, //前一个元素的序列
        timer: 0, // 储存循环的计时器序号
        translateObj: {},//touch事件时用来记录移动位置并应用到style中
        open: true, // 当前元素的动画开关
        openNext: false, // 后一个元素的动画开关
        openPre: true, // 前一个元素的动画开关
        timeOut: false, // 和setTimeout一起可确保touch事件和之后的小动画完成后再执行自动轮播
        moveOpen: false,
        btnWidth: 0
      }
    },
    watch: {
      'shufflingData' : function(val){
        this.btnWidth = this.clientInfo.width/this.shufflingData.length;
        this.caculateIndex();
      }
    },
    methods: {
      touchStart(event){
        if(!this.timeOut){
        let that = this;
          that.startX = event.changedTouches[0].pageX; //初始位置
          this.open = false;
          this.openPre = false;
          this.openNext = false;
          this.moveOpen = true;
        }
      },
      touchMove(event){
        if(this.moveOpen){
          this.movingX = event.changedTouches[0].pageX; //移动中的位置
          this.percent = ((this.movingX-this.startX)/this.clientInfo.width)*100;
          //需要响应到style中的transform属性添加,必须要用$set方法,否则不会响应到视图
          this.$set('translateObj[preIndex].transform','translate3d('+(this.percent-100)+'%, 0, 0)');
          this.$set('translateObj[nextIndex].transform','translate3d('+(this.percent+100)+'%, 0, 0)');
          this.$set('translateObj[shufflingIndex].transform','translate3d('+(this.percent)+'%, 0, 0)');
        }
      },
      touchEnd(){
        if(!this.timeOut){
          this.moveOpen = false;
          this.timeOut = true;
          this.open = true;
          this.openPre = true;
          this.openNext = true;
          this.$set('translateObj[preIndex].transform','');
          this.$set('translateObj[nextIndex].transform','');
          this.$set('translateObj[shufflingIndex].transform','');
          if(this.percent <= -30){ //假如向左滑了30%,则向左移动一屏,向左移动一屏需要关掉下一个元素的动画开关,否则后后一屏的元素会飞过去
            this.sufflingChange(); //向右侧滚动(包含最后一个元素时的处理)
            this.openNext = false;
          }else if(this.percent >= 30){ //假如向右滑了30%,则向右移动一屏,向右移动一屏需要关掉前一个元素的动画开关,否则前前一屏的元素会飞过去
            if(this.shufflingIndex == 0){ //向左侧滚动(包含第一个元素的处理)
              this.shufflingIndex = this.shufflingData.length-1;
            }else{
              this.shufflingIndex--;
            }
            this.openPre = false;
            this.caculateIndex();
          }
          setTimeout(() => { //确保移动后的动画完成,延迟和动画时间设置一致
            this.autoScroll();
            this.timeOut = false;
          }, 300);
        }
      },
      autoScroll(){ //进行自动轮播
        let that = this;
        clearInterval(that.timer);
        that.openNext = false;
        that.openPre = true;
        that.timer = setInterval(that.sufflingChange,4000);
      },
      sufflingChange(){ //向右侧滚动
        if(this.shufflingIndex == this.shufflingData.length - 1){
          this.shufflingIndex = 0;
        }else{
          this.shufflingIndex++;
        }
        this.caculateIndex();
      },
      caculateIndex(){ //计算上一个元素和下一个元素的index
        this.preIndex = this.shufflingIndex - 1 < 0 ? this.shufflingData.length-1 : this.shufflingIndex - 1;
        this.nextIndex = this.shufflingIndex + 1 >= this.shufflingData.length ? 0 : this.shufflingIndex + 1;
      }
    },
    vuex:{
      getters: {
        clientInfo : getClient
      }
    }
  }

通过写这个组件对vue的数据驱动视图的思想更了解了,感觉vue和css3真是一对好基友!用起来超级舒服!

使用方法及注意事项

使用时新建一个组件,把对应部分copy进去就可以了,比如组件叫shuffling.vue, 引入时

<shuffling :shuffling-data = 'shuffling'></shuffling>
import Shuffling from '../components/Shuffling'
export default {
  data(){
    return{
      shuffling: [
       {
         link: 'www.baidu.com',
         img: 'src.alicdn.com/fdfdfd.jpg',
         subject: '233333'
       },
       {
         link: 'www.baidu.com',
         img: 'src.alicdn.com/fdfdfd.jpg',
         subject: '233333'
       },
       {
         link: 'www.baidu.com',
         img: 'src.alicdn.com/fdfdfd.jpg',
         subject: '233333'
       }
      ]
    }
  },
components: {
    Shuffling
  }
}

组件暂时还未对2个以内的数组做兼容,2个以内将不会执行动画,只有图片切换效果。轮播进度条目前是墨瞳官网所示的轮播样式。想要改一下也会非常简单,只要利用好shufflingIndex这个属性就行了。 组件中还有一个clientInfo,这个对象是浏览器宽高的对象,我的项目中是存在vuex里的,因为很多组件都会用到,如果不需要vuex的话,可以直接写在组件里。 组件的原理注释中都写的很清楚了,理解以后能更好的应用

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-09-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 使用方法及注意事项
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档