2023-02-20 01:22:05
在 Vue3 中实现类似 Fortnite.gg 商店的图片自动切换效果,核心思路是通过 动态绑定图片数组 + CSS 过渡动画 或 第三方动画库 实现轮播。针对不同项目图片数量不同的问题,可采用以下方案:
方案 1:基于 CSS 动画 + 动态类名(推荐)通过 v-for 循环图片数组,结合 @keyframes 动画实现自动切换,无需额外依赖。
实现步骤修改数据结构确保每个商品对象包含图片数组(如 item.images),例如:
const shopList = ref([ { name: "商品A", price: 100, images: ["img1.jpg", "img2.jpg", "img3.jpg"] // 动态图片数组 }, // 其他商品...]);动态绑定图片并添加动画使用 v-for 循环图片,通过 transition-group 或 CSS @keyframes 实现切换效果:
<div class="shop-section" v-for="(items, index) in shopStore.shopList" :key="index"> <h2 class="section-name">{{ index }}</h2> <div :class="'shop-card ' + index" v-for="item in items" :style="{ height: index.includes('Jam Tracks') ? '200px' : 'auto' }" @click="preview(item)" > <!-- 图片轮播容器 --> <div class="image-carousel" :style="{ height: index.includes('Jam Tracks') ? '200px' : 'auto' }"> <img v-for="(img, imgIndex) in item.images" :key="imgIndex" :src="img" :alt="item.name" class="carousel-img" :class="{ 'active': currentImgIndex[item.id] === imgIndex }" /> </div> <div class="item-info-container"> <p class="item-name">{{ item.name }}</p> <p class="item-price"> <img style="width: 20px; vertical-align: middle;" src="@/assets/imgs/vbuck.png" alt=""> {{ item.price }} </p> </div> </div></div>添加 CSS 动画通过 @keyframes 实现淡入淡出或滑动效果:
.image-carousel { position: relative; overflow: hidden;}.carousel-img { position: absolute; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 0.5s ease;}.carousel-img.active { opacity: 1;}/* 或滑动效果 */@keyframes slide { 0% { transform: translateX(0); } 25% { transform: translateX(-100%); } 50% { transform: translateX(-100%); } 75% { transform: translateX(-200%); } 100% { transform: translateX(0); }}.slide-animation { display: flex; animation: slide 10s infinite;}通过 JavaScript 控制切换逻辑使用 setInterval 动态更新当前显示的图片索引:
import { ref, onMounted, onBeforeUnmount } from "vue';const currentImgIndex = ref({}); // 存储每个商品的当前图片索引onMounted(() => { shopStore.shopList.forEach(itemGroup => { itemGroup.forEach(item => { currentImgIndex.value[item.id] = 0; // 初始化索引 startAutoSwitch(item.id, item.images.length); }); });});function startAutoSwitch(itemId, imgCount) { let timer = setInterval(() => { currentImgIndex.value[itemId] = (currentImgIndex.value[itemId] + 1) % imgCount; }, 3000); // 每3秒切换一次 // 组件卸载时清除定时器 onBeforeUnmount(() => clearInterval(timer));}若需更复杂的交互(如手势滑动、分页器),可集成
安装 Swiper
npm install swiper在组件中使用
<template> <div class="shop-section" v-for="(items, index) in shopStore.shopList" :key="index"> <h2 class="section-name">{{ index }}</h2> <div :class="'shop-card ' + index" v-for="item in items" :style="{ height: index.includes('Jam Tracks') ? '200px' : 'auto' }" @click="preview(item)" > <!-- Swiper 容器 --> <swiper :modules="[Autoplay]" :autoplay="{ delay: 3000 }" :loop="true" :style="{ height: index.includes('Jam Tracks') ? '200px' : 'auto' }" > <swiper-slide v-for="(img, imgIndex) in item.images" :key="imgIndex"> <img :src="img" :alt="item.name" class="item-img" /> </swiper-slide> </swiper> <div class="item-info-container"> <p class="item-name">{{ item.name }}</p> <p class="item-price"> <img style="width: 20px; vertical-align: middle;" src="@/assets/imgs/vbuck.png" alt=""> {{ item.price }} </p> </div> </div> </div></template><script setup>import { Swiper, SwiperSlide } from "swiper/vue';import { Autoplay } from 'swiper/modules';import 'swiper/css';</script>纯 CSS:通过 @keyframes 或 transition + 动态类名。
JavaScript:使用 setInterval 更新索引。
第三方库:如 Swiper 提供开箱即用的轮播功能。