使用element-plus的swiper组件实现垂直效果

Lirioing2026/04/22WebFEWeb

前言

最近公司开始构建公司官网,需要用到垂直方向的轮播图,于是就通过element-plus改造了一个。

关联功能页面

响应式宽高计算工具函数Vue3组合式函数监听窗口大小变化

垂直轮播图组件

<template>
  <div class="swiper-vertical">
    <el-carousel
      ref="carouselRef"
      :interval="4000"
      :autoplay="true"
      direction="vertical"
      indicator-position="none"
      arrow="never"
      :height="carouselHeight + 'px'"
      @change="handleCarouselChange"
    >
      <el-carousel-item v-for="(item, index) in productList" :key="index">
        <div class="swiper-item">
          <img :src="item.img" alt="">
        </div>
      </el-carousel-item>
    </el-carousel>
    <div 
      :style="{
        width: indicatorWidth + 'px',
        height: indicatorHeight + 'px',
        left: indicatorLeft + 'px'
      }"
      class="swiper-indicators">
      <div style="padding-top: 0.6vw;">
        <div 
          class="swiper-indicator-arrow iconfont icon-shangjiantou" 
          @click="carouselRef.prev">
        </div>
      </div>
      <div 
        :style="{ width: miniImageWidth + 'px', height: miniImageWidth + 'px' }"
        class="swiper-indicator-item"
        :class="{'active': miniIndex === activeIndex}"
        v-for="(item, miniIndex) in productList" 
        :key="miniIndex" 
        @click="carouselRef.setActiveItem(miniIndex)">
          <img  :src="item.miniImg" alt="">
      </div>
      <div style="padding-bottom: 0.6vw;">
        <div 
          class="swiper-indicator-arrow iconfont icon-xiajiantou" 
          @click="carouselRef.next">
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref, computed } from 'vue'
import { calculateWidth, calculateHeight } from '@/utils/dimensionCalculator'
import { useWindowResize } from '@/composables/useWindowResize'

const carouselRef = ref(null)
const activeIndex = ref(0)

// 切换
const handleCarouselChange = (index) => {
  activeIndex.value = index
}
const productList = [
  {
    img: new URL('@/static/images/product/banner/product1.png', import.meta.url).href,
    miniImg: new URL('@/static/images/product/banner/product1-mini.png', import.meta.url).href,
  },
  {
    img: new URL('@/static/images/product/banner/product1.png', import.meta.url).href,
    miniImg: new URL('@/static/images/product/banner/product2-mini.png', import.meta.url).href,
  },
  {
    img: new URL('@/static/images/product/banner/product1.png', import.meta.url).href,
    miniImg: new URL('@/static/images/product/banner/product3-mini.png', import.meta.url).href,
  },
  {
    img: new URL('@/static/images/product/banner/product1.png', import.meta.url).href,
    miniImg: new URL('@/static/images/product/banner/product4-mini.png', import.meta.url).href,
  },
  {
    img: new URL('@/static/images/product/banner/product1.png', import.meta.url).href,
    miniImg: new URL('@/static/images/product/banner/product5-mini.png', import.meta.url).href,
  },
]

// 使用窗口大小监听组合式函数
useWindowResize(() => {
  calculateDimensions()
})

const resizeFlag = ref(0)
const carouselHeight = ref(710)

const indicatorWidth = ref(70)
const indicatorHeight = ref(498)
const indicatorLeft = ref(92)
const miniImageWidth = computed(() => {
  return indicatorWidth.value > 24 ? indicatorWidth.value - 6 : 18
})
// 计算轮播图高度和小图片尺寸
const calculateDimensions = () => {
  const windowWidth = window.innerWidth
  // 1920宽度下高度710,按比例计算
  carouselHeight.value = calculateHeight(1920, 1120, windowWidth)
  indicatorWidth.value = calculateWidth(70, windowWidth)
  indicatorHeight.value = calculateHeight(1920, 498, windowWidth)
  indicatorLeft.value = calculateWidth(92, windowWidth)
  resizeFlag.value++
}
</script>
<style scoped>
.swiper-vertical {
  position: relative;
  margin-top: 88px;
}
.swiper-item {
  height: 100%;
}
.swiper-item img {
  height: 100%;
  width: auto;
  display: block;
}
.swiper-indicators {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: space-evenly;
  flex-direction: column;
  gap: 1vw;
  background: rgba(25, 52, 11, 0.8);
  border-radius: 50px;
  min-width: 24px;
  min-height: 172px;
}
.swiper-indicator-item {
  display: flex;
  border-radius: 50%;
  cursor: pointer;
}
.swiper-indicator-item:hover {
  transform: scale(1.01);
  box-shadow: 0 0 10px #fff;
}
.swiper-indicator-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.swiper-indicator-item.active {
  box-shadow: 0 0 10px #fff;
}
.swiper-indicator-arrow {
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(20px, 1.25vw, 24px);
  color: #fff;
  cursor: pointer;
}
</style>

运行效果

上次更新 2026/5/8 11:16:31