<template>
  <div class='carousel' @mouseenter='hover = true' @mouseleave='hover = false'>
    <div class='carousel-inner' :style="{ transform: 'translateX(' + offset + 'px)' }">
      <div class='carousel-item' v-for='(item, index) in items' :key='index'>
        <img :src='item.image' alt=''>
      </div>
    </div>
    <nav class='carousel-nav'>
      <button class='carousel-nav-prev' @click='prev'><</button>
      <button class='carousel-nav-next' @click='next'>></button>
    </nav>
  </div>
</template>
<script>
export default {
  data() {
    return {
      items: [
        { image: 'https://picsum.photos/id/1018/800/400' },
        { image: 'https://picsum.photos/id/1015/800/400' },
        { image: 'https://picsum.photos/id/1019/800/400' },
        { image: 'https://picsum.photos/id/1020/800/400' },
        { image: 'https://picsum.photos/id/1021/800/400' }
      ],
      offset: 0,
      interval: null,
      hover: false,
      duration: 5000
    }
  },
  methods: {
    start() {
      this.stop()
      this.interval = setInterval(() => {
        this.next()
      }, this.duration)
    },
    stop() {
      clearInterval(this.interval)
    },
    prev() {
      this.stop()
      this.offset += this.itemWidth()
      if (this.offset > 0) {
        this.offset = -this.items.length * this.itemWidth() + this.itemWidth()
      }
    },
    next() {
      this.stop()
      this.offset -= this.itemWidth()
      if (this.offset < -this.items.length * this.itemWidth()) {
        this.offset = -this.itemWidth()
      }
    },
    itemWidth() {
      return this.$el.querySelector('.carousel-item').offsetWidth
    }
  },
  mounted() {
    this.start()
  },
  watch: {
    hover(value) {
      if (value) {
        this.stop()
      } else {
        this.start()
      }
    }
  }
}
</script>
<style>
.carousel {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: 400px;
}

.carousel-inner {
  display: flex;
  width: max-content;
  transition: transform 0.3s ease-in-out;
}

.carousel-item {
  flex-shrink: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.carousel-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.carousel-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  justify-content: space-between;
  width: 100%;
  height: 40px;
}

.carousel-nav button {
  background: none;
  border: none;
  font-size: 24px;
  cursor: pointer;
  outline: none;
}

.carousel-nav-prev {
  margin-left: 20px;
}

.carousel-nav-next {
  margin-right: 20px;
}
</style>
<p>该代码实现了一个基于 Vue 的轮播图组件。组件使用 <code>v-for</code> 循环展示图片,通过 <code>:style</code> 指令控制图片的偏移量实现滚动效果。左右滑动按钮使用 <code>@click</code> 事件监听点击,并调用 <code>prev</code> 和 <code>next</code> 方法控制滚动方向。鼠标悬停功能通过 <code>@mouseenter</code> 和 <code>@mouseleave</code> 事件监听鼠标进入和离开,并使用 <code>hover</code> 数据控制自动滚动状态。</p>
<p>该组件包含以下功能:</p>
<ul>
<li>无缝滚动:当滚动到最后一张图片时,会自动回到第一张图片,实现无缝滚动效果。</li>
<li>左右滑动按钮:使用左右按钮可以手动控制轮播图的滚动方向。</li>
<li>鼠标悬停暂停:当鼠标悬停在轮播图上时,自动滚动会暂停,当鼠标移开时,自动滚动会继续。</li>
</ul>
<p>该组件可以根据实际需求进行修改,例如:</p>
<ul>
<li>添加指示器:可以添加指示器来显示当前展示的图片序号。</li>
<li>改变滚动速度:可以通过调整 <code>duration</code> 数据来改变自动滚动速度。</li>
<li>添加过渡动画:可以添加过渡动画,使滚动效果更加流畅。</li>
</ul>
Vue 无缝滚动轮播图组件:带左右按钮和鼠标悬停暂停功能

原文地址: https://www.cveoy.top/t/topic/mXd1 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录