<template>
<!-- 走马灯 -->
<div class="box">
<div class="carousel">
<div class="item" v-for="(v,i) in list" :key="i" @click="open(v)">
<img :src="v.img" alt="">
<!-- 走马灯图中自定义内容 -->
<slot :current="current"></slot>
</div>
</div>
<div class="indicator" v-if="isIndicator">
<span :class="{'active': current == i}" v-for="(v,i) in list" :key="i" @click="indicatorCheck(i)"></span>
</div>
<template v-if="isArrow">
<div class="arrow_left" @click="arrowNext(1)"></div>
<div class="arrow_right" @click="arrowNext(2)"></div>
</template>
</div>
</template>
<script>
export default {
props: {
// 走马灯列表
list: {
type: Array,
required: true,
default: () => []
// { img: require(''), link: '' }
},
// 是否显示下方指示点
isIndicator: {
type: Boolean,
default: false
},
// 是否显示左右箭头
isArrow: {
type: Boolean,
default: false
},
// 自动切换的时间间隔,单位为毫秒
interval: {
type: Number,
default: 3000
}
},
data() {
return {
current: 0, // 当前在第几张图
indicator: 1,
timer: null,
}
},
mounted() {
this.init()
this.autoRun()
},
destroyed() {
clearInterval(this.timer)
},
methods: {
// 初始化走马灯列表
init() {
let carouselDom = document.querySelector('.carousel')
// 复制第一张图
let first = carouselDom.firstElementChild.cloneNode(true)
// 复制最后一张图
let last = carouselDom.lastElementChild.cloneNode(true)
// 将第一张图放在末尾
carouselDom.appendChild(first)
// 将最后一张图放在第一张
carouselDom.insertBefore(last, carouselDom.firstElementChild)
// 设置最后一张复制图为绝对定位
last.style.position = "absolute"
last.style.transform = "translateX(-100%)"
},
// 走马灯自动运行
autoRun() {
const _this = this
if(_this.indicator >= _this.list.length) {
_this.indicator = 0
}
this.timer = setInterval(() => {
this.arrowNext(2)
_this.indicator++
if(_this.indicator >= _this.list.length) {
_this.indicator = 0
}
}, this.interval)
},
// 下方指示器事件
indicatorCheck(index) {
let carouselDom = document.querySelector('.carousel')
let count = this.list.length
// 当前在最后一张图时,无缝切换到第一页
if(this.current === count-1 && index === 0) {
carouselDom.style.transform = "translateX(100%)"
carouselDom.style.transition = 'none'
carouselDom.clientHeight // 强制渲染
this.moveTo(0, 'move')
} else {
this.moveTo(index, 'move')
}
},
// 走马灯左右箭头事件
arrowNext(type) {
let carouselDom = document.querySelector('.carousel')
let count = this.list.length
// 左箭头
if(type==1) {
// 当前是否在第一张图,无缝切换
if(this.current === 0) {
carouselDom.style.transform = `translateX(-${count}00%)`
carouselDom.style.transition = 'none'
carouselDom.clientHeight // 强制渲染
this.moveTo(count-1, 'move')
} else {
this.moveTo(this.current-1, 'move')
}
}
// 右箭头
if(type==2) {
// 当前是否在最后一张图,无缝切换
if(this.current === count-1) {
carouselDom.style.transform = "translateX(100%)"
carouselDom.style.transition = 'none'
carouselDom.clientHeight // 强制渲染
this.moveTo(0, 'move')
} else {
this.moveTo(this.current+1, 'move')
}
}
},
moveTo(index, type) {
if(type=='move') {
clearInterval(this.timer)
this.indicator = index+1
this.autoRun()
}
this.current = index
let carouselDom = document.querySelector('.carousel')
carouselDom.style.transform = `translateX(-${index}00%)`
carouselDom.style.transition = '.5s'
},
// 跳转
open(v) {
if(v.link) {
window.open(v.link)
}
}
}
}
</script>
<style scoped lang="scss">
.box{
width: 100%;
height: 700px;
margin: 0 auto;
overflow: hidden;
position: relative;
.carousel{
width: 100%;
display: flex;
transform: translateX(-0%);
.item{
width: 100%;
position: relative;
> img{
width: calc(100vw - 4px);
// height: 700px;
display: block;
}
}
}
.indicator{
position: absolute;
bottom: 200px;
left: 50%;
transform: translateX(-50%);
display: flex;
justify-content: center;
span{
display: block;
width: 20px;
height: 20px;
border: 1px solid #ddd;
border-radius: 50%;
margin: 0 4px;
cursor: pointer;
&.active{
background-color: #fff;
border-color: #fff;
}
}
}
.arrow_left,
.arrow_right{
width: 30px;
height: 30px;
background-color: #ccc;
position: absolute;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
}
.arrow_left{
left: 300px;
}
.arrow_right{
right: 300px;
}
}
</style>