移动端vue轮播图组件 - 代码

这是一个使用Vue.js编写的Swiper组件,包括Swiper.vue和SwiperItem.vue两个部分。Swiper.vue实现了轮播图的基本功能,如自动播放、触摸滑动切换、小圆点指示器等。SwiperItem.vue作为轮播图的每个项目容器。在HomeSwiper.vue中,通过v-for指令渲染多个SwiperItem,展示了如何在实际项目中使用这个轮播图组件。
摘要由CSDN通过智能技术生成
1. Swiper.vue
<template>
  <div class="swiper">
    <!-- 显示轮播图片区域 -->
    <div class="slide" @touchstart="touchstart" @touchend="touchend" @touchmove="touchmove">
      <slot></slot>
    </div>

    <!-- 小圆点显示区 -->
    <div>
      <ul class="indicator" v-show="showIndicator && slideNum > 1">
        <li v-for="(item,i) in slideNum" :key="i" :class="{active:i === currentIndex-1}" class="indi-item"></li>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  name: "Swiper",
  props:{
    /* 播放图片的间隔时间 */
    interval: {
      type: Number,
      default: 3000
    },
    /** 设置一个比例,当手指拖动的距离到达图片的几分之一是,图片被移动 */
    moveRatio: {
      type: Number,
      default: 0.25
    },
    /** 动画持续时间 */
    animDuration: {   
      type: Number,
      default: 300
    },
    /** 是否显示小圆点 */
    showIndicator: {
      type: Boolean,
      default: true
    }
  },
  data(){
    return{
      slideNum: 0,  // 图片个数
      currentIndex: 1,  // 当前播放图片的index
      totalWidth: 0,  // 轮播图的总宽度
      timer: null,  // 定时器
      slideStyle:{}, // 存储slide的样式
      scrolling: false  // 图片是否在滑动
    }
  },
  mounted(){
  	// 在mounted中调用以下两个函数,是因为mounted是Vue实例创建期间的最后一个声明周期函数
  	// mounted执行时在内存中编译好的模板已经真实挂载到页面中,用户可以看到渲染好的页面
  	// 此时也可以进行dom操作而不会报错了
    // 1.操作DOM, 在前后添加Slide
    this.handleDom();
    // 2.开启定时器
    this.startTimer();
  },
  methods:{
    /*
      通过设置定时器让图片自动播放
    */
    startTimer:function(){
      this.timer = window.setInterval(()=>{
        // 通过定时器不断的循环改变currentIndex来使图片自动向左移动
        this.currentIndex++;
        this.scrollContent(-this.currentIndex * this.totalWidth);
      },this.interval)
    },

    /*
      清除定时器
    */
    stopTimer:function(){
      window.clearInterval(this.timer);
    },

    /**
     * 操作dom
     */
    handleDom:function(){
      // 根据要求跟第一张图片复制一张放到最后
      // 将最后一张图片复制一张放到第一张前面

      // 获取要操作的元素
      let swiperEl = document.querySelector('.slide');
      let swiperitems = swiperEl.getElementsByClassName('swiperitem');
      // 保存图片个数
      this.slideNum = swiperitems.length;
      // 当图片张数>1的时候才好复制
      if (this.slideNum > 1) {
        //复制图片
        let firstClone = swiperitems[0].cloneNode(true);
        let lastClone = swiperitems[this.slideNum-1].cloneNode(true);
        // 将复制的图片插入到想要的位置
        swiperEl.insertBefore(lastClone, swiperitems[0]);
        swiperEl.appendChild(firstClone);

        // 轮播区域的宽度
        this.totalWidth = swiperEl.offsetWidth;
        this.slideStyle = swiperEl.style;
        
      }
      // 让轮播图显示没复制图片时的第一张,现在显示的是复制过来的最后一张
      // 复制后,第一张图片的后面就是我们想要显示的,加上totalWidth表示的就是一张图片的宽度
      // 所以直接向左移动-this.totalWidth的距离
      this.animate(-this.totalWidth);

	  // 监听屏幕宽度变化
      // 因为onresize在监听过程中会多次触发,所以使用一个定时器
      var firstTimer = null;
      window.onresize = ()=>{
        if (firstTimer) {
          clearTimeout(firstTimer);
        }
        firstTimer = setTimeout(()=>{
          // 当监听到屏幕宽度发生变化时,改变this.totalWidth
          this.totalWidth = swiperEl.offsetWidth;
          this.animate(-this.totalWidth);
          this.currentIndex = 1;
        },100)
      }
    },

    /**
     * 实现动画函数
     */
    animate:function(target){
      // 通过transform来设置移动距离
      this.slideStyle.transform = `translate3d(${target}px, 0, 0)`;
      this.slideStyle['-webkit-transform'] = `translate3d(${target}px), 0, 0`;
      this.slideStyle['-ms-transform'] = `translate3d(${target}px), 0, 0`;
    },

    /**
     * 调整动画
     */
    checkPosition:function(){ 
      window.setTimeout(()=>{
        // 1.校验正确的位置
        // 这里将this.slideStyle.transition 重新归零,这样待会重定位的时候就不会缓慢移动,显示出重定向的过程
        this.slideStyle.transition = '0ms';
        if(this.currentIndex >= this.slideNum + 1){
          // 当轮播到最后最后一张图片时,再重新定位到第一张开始播放
          // 这里的第一张不是索引值为0的第一张,是我们图片要求摆放在第一个的
          this.currentIndex = 1;
          // 下标值为0的图片和下标值为5的图片是我们前面复制的,分别跟下标值为4和下标值为1的图片重复
          // 下标值为5的图片作为过渡图片,一播放到他就应该立马跳转到下标值为1的图片开始播放
          // 在重定向index后,如果不调用一下animate函数,那么轮播图就会直接从下标值为5的图片跳转到下标值为2的那张
          // 这是因为这里改变了currentIndex但是没有使用,当checkPosition()运行完一次,再循环timer定时器调用scrollContent函数时
          // currentIndex的值为2,跳过了播放下标值为1的那张图片直接到他的下一张,中间没有过渡导致用户能看到转换的过程,用户体验较差
          this.animate(-this.currentIndex * this.totalWidth);
        }else if(this.currentIndex <= 0){
          this.currentIndex = this.slideNum;
          this.animate(-this.currentIndex * this.totalWidth);
        }
      }, this.animDuration)
    },
    scrollContent: function(position){ 
      // 1.设置图片正在滑动
      this.scrolling = true;
      this.slideStyle.transition ='transform '+ this.animDuration + 'ms';
      // 3. 播放动画
      this.animate(position);
      // 2. 判断currentIndex的值是否符合要求
      this.checkPosition();
      // 4.图片滑动结束
      this.scrolling = false;
    },

    // 设置touch事件
    /**
     * 手指触摸到一个 DOM 元素时触发
     */
    touchstart:function(e){
      // 1.判断此时图片是否在滑动,图片在滑动的话不能进行操作
      if(this.scrolling) return
      // 2. 图片在滑动的话就停止定时器
      this.stopTimer();
      // 3.记录手指刚触摸屏幕时的位置
      this.startX = e.touches[0].pageX;
    },

    /**
     * 手指在一个 DOM 元素上滑动时触发
     */
    touchmove:function(e){
      // 记录手指在屏幕是上移动后的位置
      this.currentX = e.touches[0].pageX;
      // 计算出移动的距离
      this.distance = this.currentX - this.startX;
      let currentPosition = -this.currentIndex * this.totalWidth;
      let moveDistance = this.distance + currentPosition;
      this.animate(moveDistance);
      this.scrolling = true;
    },

    /**
     * 手指从一个 DOM 元素上移开时触发
     */
    touchend:function(){
    	// 在手指拖动图片后在进行计算
    	// 解决了不断触摸屏幕图片一直播放的问题
    	if(this.scrolling){
	      // 获取移动的距离
	      let currentMove = Math.abs(this.distance);
	      if (this.distance === 0) {
	        return
	      }else if (this.distance > 0 && currentMove > this.totalWidth * this.moveRatio) {
	        // 当图片被向右拖动时,currentIndex--,显示前一张图片
	        this.currentIndex--;
	      } else if(this.distance < 0 && currentMove > this.totalWidth * this.moveRatio){
	        // 当图片被向左拖动时,currentIndex++,显示后一张图片
	        this.currentIndex++;
	      }
		}
      // 3.移动到正确的位置
      this.scrollContent(-this.currentIndex * this.totalWidth);
      // 4.移动完成后重新开启定时器
      this.startTimer();
    }
  }
}
</script> 
<style scoped>
  .swiper{
    overflow: hidden;
    position: relative;
  }
  .slide{
    display: flex;
  }
  .indicator {
    display: flex;
    justify-content: center;
    position: absolute;
    width: 100%;
    bottom: 8px;
  }
  .indi-item {
    box-sizing: border-box;
    width: 8px;
    height: 8px;
    border-radius: 4px;
    background-color: #fff;
    line-height: 8px;
    text-align: center;
    font-size: 12px;
    margin: 0 5px;
  }
  .indi-item.active {
    background-color: rgba(212,62,46,1.0);
  }
</style>
2. SwiperItem.vue
<template>
  <div class="swiperitem">
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: "SwiperItem",
}
</script>

<style>
  .swiperitem{
    width: 100%;
    flex-shrink: 0;
  }
  .swiperitem img{
    width: 100%;
  }
</style>
3. index.js
  • index.js :导出Swiper.vueSwiperItem.vue
import Swiper from './Swiper'
import SwiperItem from './SwiperItem'

export {
  Swiper, SwiperItem
}
4. HomeSwiper.vue
<template>
  <div class="homeswiper">
    <swiper>
      <swiper-item v-for="(item,i) in imgMessage" :key="i">
        <a :href="item.url">
          <img :src="item.path" alt="">
        </a>
      </swiper-item>
    </swiper>
  </div>
</template>

<script>
  import {Swiper, SwiperItem} from "../../components/swiper"

  export default {
      name: "HomeSwiper",
      components:{
        Swiper, SwiperItem
      },
      props:{},
      data(){
        return{
          imgMessage:[
            {path: require("@/assets/img/slide_1.jpg"), url: "javascript:;" },
            {path: require("@/assets/img/slide_2.jpg"), url: "javascript:;" },
            {path: require("@/assets/img/slide_3.jpg"), url: "javascript:;" },
            {path: require("@/assets/img/slide_4.jpg"), url: "javascript:;" }
          ],
        }
      }
  }
</script>

<style scoped>
  a{
    display: block;
    height: 100%;
    
  }
</style>
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue移动端轮播图可以通过使用Vue的生命周期钩子函数和一些插件或库来实现。以下是一种简单实现轮播图的方法: 1. 安装依赖:使用npm或者yarn安装vue-awesome-swiper插件,这是一个针对移动端开发的swiper插件。 2. 在Vue组件中引入依赖: ```javascript import 'swiper/css/swiper.css'; import VueAwesomeSwiper from 'vue-awesome-swiper'; Vue.use(VueAwesomeSwiper); ``` 3. 在Vue组件中使用轮播图: ```html <template> <div class="swiper"> <swiper :options="swiperOptions"> <swiper-slide v-for="(item, index) in images" :key="index"> <img :src="item.src" :alt="item.alt"> </swiper-slide> <div class="swiper-pagination" slot="pagination"></div> </swiper> </div> </template> <script> export default { data() { return { swiperOptions: { autoplay: true, // 自动播放 pagination: { // 分页器设置 el: '.swiper-pagination' } }, images: [ { src: 'image1.jpg', alt: '图片1' }, { src: 'image2.jpg', alt: '图片2' }, { src: 'image3.jpg', alt: '图片3' } ] } } } </script> <style> .swiper { width: 100%; height: 100%; } .swiper .swiper-pagination { position: absolute; bottom: 10px; left: 0; right: 0; text-align: center; } </style> ``` 这个例子中,我们首先安装了vue-awesome-swiper插件,并在Vue组件中引入和使用。通过设置swiperOptions对象来配置轮播图的选项,例如自动播放和分页器设置等。在images数组中定义了轮播图的图片和对应的alt文本。通过v-for循环遍历images数组,为每个图片创建一个swiper-slide。在使用分页器时,通过定义slot="pagination"将分页器添加到相应的位置。最后,通过样式设置轮播图的宽度和高度,以及分页器的位置。 这只是一个简单的示例,根据具体需求,我们可以进一步对轮播图进行定制和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值