vue中轮播图的实现

在这里插入图片描述
轮播图中html结构一般由主体图片、下方小圆圈、上一张和下一张组成。

主体图片能够实现两秒切换一次,并且对应的小圆圈被选中

点击上一张和下一张按钮切换相应图片,同时小圆圈产生变化。

点击小圆圈切换图片

鼠标放在图片主体上停止轮播,鼠标离开主体图片开始轮播。

html结构

<div class="container">
    <div class="lunbo" @mouseenter="clear" @mouseleave="run">
        //1、主体图片
      <div class="img">
        <img :src="dataList[currentIndex]" alt="" />
      </div>
        //2、下方圆圈
      <div class="dooted" v-if="this.dataList.length">
        <ul class="doo">
          <li
            v-for="(item, index) in this.dataList"
            :key="index"
            :class="{ current: currentIndex == index }"
            @click="gotoPage(index)"
          ></li>
        </ul>
      </div>
        //3、下一张
      <div class="right turn" @click="next()">
        <i class="el-icon-arrow-right"></i>
      </div>
        //4、上一张
      <div class="left turn" @click="up()">
        <i class="el-icon-arrow-left"></i>
      </div>
    </div>
  </div>

data()

data中定义轮播的图片,显示图片的索引值,定时器。

通过索引值来控制展示哪张图片

  data () {
    return {
      dataList: [
        'https://i1.mifile.cn/a4/xmad_15535933141925_ulkYv.jpg',
        'https://i1.mifile.cn/a4/xmad_15532384207972_iJXSx.jpg',
        'https://i1.mifile.cn/a4/xmad_15517939170939_oiXCK.jpg'
      ],
      currentIndex: 0, // 默认显示图片
      timer: null // 定时器
    }
  },

created

created中 进入就开始轮播

  created () {
    this.run()
  },

methods

methods中

  methods: {
      //点击小圆圈切换图片
    gotoPage (index) {
      this.currentIndex = index
    },
      //下一张
    next () {
      if (this.currentIndex === this.dataList.length - 1) {
        this.currentIndex = 0
      } else {
        this.currentIndex++
      }
    },
      //上一张
    up () {
      if (this.currentIndex === 0) {
        this.currentIndex = this.dataList.length - 1
      } else {
        this.currentIndex--
      }
    },
      //清除定时器
    clear () {
      clearInterval(this.timer)
    },
    // 定时器
    run () {
      this.timer = setInterval(() => {
        this.next()
      }, 2000)
    }
  }

完整代码

<template>
  <div class="container">
    <div class="lunbo" @mouseenter="clear" @mouseleave="run">
      <div class="img">
        <img :src="dataList[currentIndex]" alt="" />
      </div>
      <div class="dooted" v-if="this.dataList.length">
        <ul class="doo">
          <li
            v-for="(item, index) in this.dataList"
            :key="index"
            :class="{ current: currentIndex == index }"
            @click="gotoPage(index)"
          ></li>
        </ul>
      </div>
      <div class="right turn" @click="next()">
        <i class="el-icon-arrow-right"></i>
      </div>
      <div class="left turn" @click="up()">
        <i class="el-icon-arrow-left"></i>
      </div>
    </div>

  </div>
</template>

<script>
export default {
  data () {
    return {
      dataList: [
        'https://i1.mifile.cn/a4/xmad_15535933141925_ulkYv.jpg',
        'https://i1.mifile.cn/a4/xmad_15532384207972_iJXSx.jpg',
        'https://i1.mifile.cn/a4/xmad_15517939170939_oiXCK.jpg'
      ],
      currentIndex: 0, // 默认显示图片
      timer: null // 定时器
    }
  },
  created () {
    this.run()
  },
  methods: {
    gotoPage (index) {
      this.currentIndex = index
    },
    next () {
      if (this.currentIndex === this.dataList.length - 1) {
        this.currentIndex = 0
      } else {
        this.currentIndex++
      }
    },
    up () {
      if (this.currentIndex === 0) {
        this.currentIndex = this.dataList.length - 1
      } else {
        this.currentIndex--
      }
    },
    clear () {
      clearInterval(this.timer)
    },
    // 定时器
    run () {
      this.timer = setInterval(() => {
        this.next()
      }, 2000)
    }
  }
}
</script>

<style lang="less" scoped>
ul li {
  float: left;
  width: 30px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  cursor: pointer;
  color: rgba(240, 238, 238, 0.8);
  font-size: 14px;
}
.container {
  position: relative;
  height: 200px;
  width: 402px;
  margin: 0 400px;
  .img {
    height: 200px;
    width: 400px;
    border: 1px solid gray;
    img {
      height: 100%;
      width: 100%;
    }
  }
  .dooted {
    position: absolute;
    bottom: -10px;
    right: 0px;
  }
}
.turn {
  width: 20px;
  height: 20px;
  line-height: 20px;
  border-radius: 5px;
  cursor: pointer;
  background-color: #d0d0d073;
}
.right {
  position: absolute;
  top: 100px;
  right: 0;
}
.left {
  position: absolute;
  top: 100px;
  left: 0;
}
.current {
  color: gray;
}
</style>

方法2,代码如下:

<template>
  <div id="app">
    <div class="SwiperBox" @mouseenter="MouseFun('移入')" @mouseleave="MouseFun('移出')">
      <!-- 图片 -->
      <img :class="['imgCss',ShowImg==index?'ShowCss':'']"
           :src="item.imgUrl" v-for="(item,index) in imgList" :key="index" />
      <!-- 左箭头按钮 -->
      <div class="leftBtn" @click="throttle(PrevFun)">&larr;</div>
      <!-- 右箭头按钮 -->
      <div class="rightBtn" @click="throttle(NextFun)">&rarr;</div>
      <!-- 下方指示点容器 -->
      <div class="instBox">
        <div v-for="(item,index) in imgList.length" :key="index"
             @click="ShowImg=index" :class="['inst',ShowImg==index?'instActv':'']">
        </div>
      </div>
    </div>
  </div>
  </template>

<script>
  export default {
    components: {},
    data() {
      return {
        imgList: [
          {imgUrl: "https://img14.360buyimg.com/pop/s590x470_jfs/t1/107362/20/24177/90602/6233decdE5627d944/b7194e538e3c8c7a.jpg"},
          {imgUrl: "https://img12.360buyimg.com/pop/s590x470_jfs/t1/204028/36/25480/101429/62f507a7Ec62b0cd3/db5984ae24ce0212.jpg"},
          {imgUrl: "https://imgcps.jd.com/ling4/100022552927/5Lqs6YCJ5aW96LSn/5L2g5YC85b6X5oul5pyJ/p-5f3a47329785549f6bc7a6e6/075268d0/cr/s/q.jpg"},
          {imgUrl: "https://imgcps.jd.com/ling4/100026667910/5Lqs6YCJ5aW96LSn/5L2g5YC85b6X5oul5pyJ/p-5f3a47329785549f6bc7a6e3/d7b3695b/cr/s/q.jpg"},
          {imgUrl: "https://img30.360buyimg.com/pop/s590x470_jfs/t1/201288/25/23710/64955/62f070fdE95cb4f47/22b916d938a43bb5.jpg"}
        ],
        ShowImg:0,  // 表示当前显示的图片
        flag:true, // 用来节流防止重复点击
        start:null, // 自动执行下一张定时器
      };
    },
    mounted() {
      this.setTimeoFun()
    },
    methods: {
      // 这里定义一个鼠标移入移出事件,鼠标悬停时停止自动轮播,鼠标移出则重新执行自动轮播
      MouseFun(type){// 停止定时器            // 重新执行定时器
        type=='移入'?clearTimeout(this.start):this.setTimeoFun()
      },
      setTimeoFun(){
        this.start = setInterval(()=>{
          this.NextFun()
        },1500)
      },
      // 这里通过额外封装的节流函数触发 PrevFun() 和 NextFun(),以达到防止重复点击的效果
      throttle(fun) {
        if (this.flag) {
          this.flag = false;
          fun(); // 此为模板中传递进来的PrevFun()或NextFun()函数
          setTimeout(() => {
            this.flag = true;
          }, 100); // 节流间隔时间
        }
      },
      // 上一张
      PrevFun(){
        if(this.ShowImg!==0){
          this.ShowImg--
        }else{
          this.ShowImg=this.imgList.length-1
        }
      },
      // 下一张
      NextFun(){
        if(this.ShowImg!==this.imgList.length-1){
          this.ShowImg++
        }else{
          this.ShowImg=0
        }
      },
    }
  };
</script>

<style lang="less" scoped>
  /* 图片容器样式 */
  .SwiperBox {
    position: relative;
    width: 500px;
    height: 300px;
    border: 1px solid #ccc;
    box-sizing: border-box;
    cursor: pointer;
  }
  /* 图片默认样式 */
  .imgCss {
    position: absolute;
    left: 0px;
    top: 0px;
    width: 500px;
    height: 300px;
    opacity: 0;
    transition: 0.8s;  /* 淡入淡出过渡时间 */
  }
  /* 图片选中样式(继承上方默认样式) */
  .ShowCss {
    opacity: 1;
  }
  /* 两个按钮共有的样式,也可直接使用箭头图片替代 */
  .leftBtn,
  .rightBtn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 30px;
    height: 30px;
    display: flex;
    justify-content: center;
    align-items: center;
    background: rgba(109, 109, 109, 0.445);
    color: #fff;
    border-radius: 50%;
    cursor: pointer;
    font-size: 12px;
    font-weight: 500;
  }
  .leftBtn {
    left: 10px;
  }
  .rightBtn {
    right: 10px;
  }
  /* 下方指示器盒子 */
  .instBox{
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: 10px;
    display: flex;
  }
  /* 小圆点 */
  .inst{
    width: 10px;
    height: 10px;
    border: 1px solid #ccc;
    margin-right: 8px;
    background: #fff;
    border-radius: 50%;
    cursor: pointer;
  }
  .inst:last-child{
    margin-right: 0px;
  }
  .instActv{
    border: 1px solid #ff0000;
    background: #ff0000;
  }
  #app{
    width: 100%;
    padding: 120px;
    display: flex;
    justify-content: center;
  }
</style>

效果图如下:
在这里插入图片描述

方法3:多张图片轮播效果

<template>
    <div class="swiperBox">
        <img class="imgLeft" @click="clickLeft" src="../../../assets/img/左.png" alt="">
        <img class="imgRight" @click="clickRight" src="../../../assets/img/右.png" alt="">
        <div id="swiper">
            <div class="imgBox">
                <div class="imgDiv" v-for="(item,index) of imgList" :key="index">
                    <img :src="item" />
                </div>
            </div>
        </div>
    </div>
</template>
<script>
export default {
    name: 'BaseSwiper',
    props: {
        speed: Number,
        direction: String,
    },
    data() {
        return {
            imgList: [
                require('../../../assets/img/14.png'),
                require('../../../assets/img/15.png'),
                require('../../../assets/img/17.png'),
                require('../../../assets/img/18.png'),
                require('../../../assets/img/24.png'),
            ],
            timer: null,
            theSpeed: this.speed,
            imgWidth: 260,
            theDirection: this.direction,
        }
    },
    methods: {
        clickLeft() {
            this.theDirection = 'left';
        },
        clickRight() {
            this.theDirection = 'right';
        },
    },
    mounted() {
        let imgBox = document.getElementsByClassName('imgBox')[0];
        //将imgBox下的图片进行拼接 循环展示图片
        imgBox.innerHTML += imgBox.innerHTML;
        let imgDiv = document.getElementsByClassName('imgDiv');
        imgBox.style.width = imgDiv.length * this.imgWidth + 'px';//设置div的宽度使图片可以放下
        let self = this;
        console.log(imgBox.offsetWidth,imgBox.style.width )
        function autoScroll() {
            if (imgBox.offsetLeft < -(imgBox.offsetWidth / 2)) {//提前更新left值,实现循环展示
                imgBox.style.left = 0;
            }
            if (imgBox.offsetLeft > 0) {//向右滚动 提前更新left值,实现循环展示
                imgBox.style.left = -(imgBox.offsetWidth / 2) + 'px';
            }
            if (self.theDirection == 'left') { //向左滚动,值为负
                self.theSpeed = -Math.abs(self.theSpeed)
            } else { //向右滚动
                self.theSpeed = Math.abs(self.theSpeed)
            }
            // 求出总的left值,等于left值加上移动的速度(px值)
            imgBox.style.left = imgBox.offsetLeft + self.theSpeed + 'px';
        }
        this.timer = setInterval(autoScroll, 30);//全局变量 ,保存返回的定时器
    },
    beforeDestroy() {
        clearInterval(this.timer);
        this.timer = null;
    }
}
</script>
<style scoped lang='less'>
.swiperBox {
    height: 100%;
    width: 100%;
    position: relative;
    .imgLeft {
        left: 0;
        top: 40%;
    }
    .imgLeft,
    .imgRight {
        width: 27px;
        height: 38px;
        position: absolute;
        cursor: pointer;
    }
    .imgRight {
        right: 0;
        top: 40%;
    }
    .directionIcon:hover {
        opacity: 1;
    }
    #swiper {
        width: 90%;
        height: 100%;
        margin: 0 auto;
        overflow: hidden;
        position: relative;
        .imgBox {
            height: 100%;
            position: absolute;
            left: 0;
            top: 0;
            overflow: hidden;
            display: flex;
            .imgDiv {
                width: 100%;
                margin-left: 15px;
                img {
                    height: 100%;
                    width: 280px;
                    // width: 260px;
                    // height: 120px;
                }
            }
        }
    }
}
</style>

展示效果图:
在这里插入图片描述

Logo

前往低代码交流专区

更多推荐