先看效果
编写组件代码 CarouselChart.vue
<template>
<div class='img-box'>
<el-button @click='previousImages' v-if='props.showBtn'>←</el-button>
<div class='img'>
<div style='display: flex;gap: 20px' id='move'>
<img
class='img-item' v-for='(item) in props.imgList'
:key='item.src'
:src='item.src'
alt='' />
</div>
</div>
<el-button @click='nextImages' v-if='props.showBtn'>→</el-button>
<div class='spots' v-if='props.showSpot'>
<div
class='spot'
v-for='(item,index) in props.imgList.length / 2'
:key='index'
:class="{
'active':index*2 === currentIndex
}"
@click='setCurIndex(index)'
>
</div>
</div>
</div>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue'
const emit = defineEmits(['handlePrev', 'handleNext'])
const props = defineProps({
// 图片
imgList: {
type: Object,
required: true,
},
// 是否显示左右切换按钮
showBtn: {
type: Boolean,
default: true,
},
// 是否显示小圆点
showSpot: {
type: Boolean,
default: true,
},
})
const currentIndex = ref(0)
const updateVisibleImages = () => {
const imgDom = document.querySelector('#move')
imgDom.style.transform = `translateX(-${((currentIndex.value * 440) + ((currentIndex.value) * 20))}px)`
imgDom.style.transition = `all 0.5s`
}
const nextImages = () => {
if (currentIndex.value + 2 >= props.imgList.length) return
currentIndex.value += 2
updateVisibleImages()
emit('handleNext')
}
const previousImages = () => {
if (currentIndex.value <= 0) return
currentIndex.value -= 2
updateVisibleImages()
emit('handlePrev')
}
const setCurIndex = (index) => {
currentIndex.value = index * 2
updateVisibleImages()
}
</script>
<style scoped lang='scss'>
.img-box {
display: flex;
align-items: center;
justify-content: center;
gap: 20px;
width: 100%;
height: 100%;
position: relative;
.img {
width: 900px;
overflow: hidden;
transition: all 0.5s;
.img-item {
width: 440px;
img {
width: 100%;
}
}
}
.spots {
position: absolute;
left: 50%;
margin-top: 20%;
transform: translateX(-50%);
display: flex;
gap: 20px;
align-items: center;
justify-content: center;
.spot {
width: 10px;
height: 10px;
border-radius: 5px;
background-color: #1a60ea;
transition: all 0.5s;
cursor: pointer;
&:hover {
transform: scale(1.5);
}
}
.active {
background-color: #ea1ccc;
transform: scale(2);
transition: all 0.5s;
}
}
}
</style>
使用这个组件
<template>
<div class='h-full w-full flex align-center justify-center'>
<CarouselChart
:img-list='imgList'
@handlePrev='handlePrev'
@handleNext='handleNext'
/>
</div>
</template>
<script setup>
import { reactive } from 'vue'
import { ElMessage } from 'element-plus'
import img1 from '@/assets/lunbo/01.jpg'
import img2 from '@/assets/lunbo/02.jpg'
import img3 from '@/assets/lunbo/03.jpg'
import img4 from '@/assets/lunbo/04.jpg'
import img5 from '@/assets/lunbo/05.jpg'
import img6 from '@/assets/lunbo/06.jpg'
import img7 from '@/assets/lunbo/07.jpg'
import img8 from '@/assets/lunbo/08.jpg'
import img9 from '@/assets/lunbo/09.jpg'
import img10 from '@/assets/lunbo/10.jpg'
let imgList = reactive([
{ src: img1 },
{ src: img2 },
{ src: img3 },
{ src: img4 },
{ src: img5 },
{ src: img6 },
{ src: img7 },
{ src: img8 },
{ src: img9 },
{ src: img10 },
])
function handleNext() {
ElMessage.warning('下一张')
}
function handlePrev() {
ElMessage.success('上一张')
}
</script>