<template>
  <div class='carousel'>
    <div class='carousel-wrap' :style='wrapStyle'>
      <div class='carousel-item' v-for='(item, index) in items' :key='index'>
        <img :src='item.src' alt=''>
      </div>
    </div>
    <div class='carousel-control'>
      <button class='carousel-prev' @click='handlePrev'>&lt;</button>
      <button class='carousel-next' @click='handleNext'>&gt;</button>
    </div>
  </div>
</template>
<style>
.carousel {
  width: 100%;
  position: relative;
  overflow: hidden;
}
.carousel-wrap {
  display: flex;
  width: 300%;
  transition: transform 0.5s ease;
}
.carousel-item {
  flex: 1;
  margin-right: 10px;
}
.carousel-item img {
  width: 100%;
}
.carousel-control {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 100%;
  height: 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.carousel-prev,
.carousel-next {
  width: 40px;
  height: 40px;
  border: none;
  outline: none;
  background-color: rgba(0, 0, 0, 0.5);
  color: #fff;
  font-size: 24px;
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 0.3s ease;
}
.carousel-prev:hover,
.carousel-next:hover {
  opacity: 1;
}
</style>
<script>
export default {
  data() {
    return {
      items: [
        { src: 'http://placehold.it/400x200/ff0000' },
        { src: 'http://placehold.it/400x200/00ff00' },
        { src: 'http://placehold.it/400x200/0000ff' },
        { src: 'http://placehold.it/400x200/ffff00' },
        { src: 'http://placehold.it/400x200/00ffff' },
        { src: 'http://placehold.it/400x200/ff00ff' }
      ],
      currentIndex: 0,
      timer: null,
      isPaused: false
    }
  },
  computed: {
    wrapStyle() {
      return {
        transform: `translateX(-${this.currentIndex * 100}%)`
      }
    }
  },
  mounted() {
    this.startTimer()
  },
  methods: {
    startTimer() {
      this.timer = setInterval(() => {
        if (!this.isPaused) {
          this.handleNext()
        }
      }, 3000)
    },
    handlePrev() {
      this.currentIndex = (this.currentIndex - 1 + this.items.length) % this.items.length
    },
    handleNext() {
      this.currentIndex = (this.currentIndex + 1) % this.items.length
    }
  },
  watch: {
    currentIndex(newIndex) {
      if (newIndex === 0) {
        setTimeout(() => {
          this.currentIndex = this.items.length - 1
        }, 500)
      } else if (newIndex === this.items.length - 1) {
        setTimeout(() => {
          this.currentIndex = 0
        }, 500)
      }
    }
  }
}
</script>
<p>在这个示例中,轮播图的每个图片都用一个对象来表示,包含图片的 URL 地址等信息。轮播图的核心是通过 CSS 的 <code>transform</code> 属性实现滚动,每次滚动的距离是当前图片宽度的百分比,因此 CSS 样式中需要设置 <code>carousel-wrap</code> 元素的宽度为所有图片宽度的三倍。</p>
<p>定时滚动功能通过 <code>setInterval</code> 函数实现,每隔 3 秒钟切换到下一个图片。左右控制按钮通过 <code>handlePrev</code> 和 <code>handleNext</code> 方法实现,点击按钮时切换到上一个或下一个图片。滚动到最后一张或第一张图片时,使用 <code>setTimeout</code> 函数等待过渡动画结束后,将当前索引重置到第一张或最后一张图片。</p>
<p>鼠标悬停暂停功能通过 <code>isPaused</code> 变量和 <code>mouseover</code> 和 <code>mouseout</code> 事件实现,当鼠标悬停在轮播图上时,设置 <code>isPaused</code> 为 <code>true</code>,停止定时滚动;当鼠标移开时,设置 <code>isPaused</code> 为 <code>false</code>,继续定时滚动。</p>
Vue 实现无缝滚动轮播图:带按钮控制、鼠标悬停暂停

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

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