主要用css控制元素位置,展示的内容脱离文档流后,设置当前元素的前、中、后,三个元素的位置。
遇到的问题:
- 需要存上一个展示的
index
;用于设置过度时的动画。 transition
动画时间属性只能设置在切换时的前、后;两个属性内。不然会出现调整元素位置的时候有明细的过度动画。- 控制
transform: translateX(px)
位置时,需要判断是否第一个和最后一个元素,单独处理;其他的元素正常横排就行;
贴上代码组件,目前只完成了基本功能,可以自行修改,比如增加鼠标指向时间,左右切换的节流等等:
<template>
<div class="banner">
<div class="img-box">
<div
v-for="(item, index) in banner"
:key="index"
class="img-item"
:class="{ active: bannerIndex === index || bannerIndex2 === index }"
:style="bannerStyle(index)"
>
{{ index }}
</div>
</div>
<div class="arrows">
<div class="left" @click="bannerLeft"><</div>
<div class="right" @click="bannerRight">></div>
</div>
<div class="dots">
<span
v-for="(item, index) in banner"
:key="index"
:class="{ active: index === bannerIndex }"
@click="onClickDot(index)"
></span>
</div>
</div>
</template>
<script>
export default {
data() {
return {
banner: 6,
bannerIndex: 0,
bannerIndex2: 0,
t: null,
};
},
mounted() {
// this.scrollBanner();
},
methods: {
scrollBanner() {
this.t && clearInterval(this.t);
this.t = setInterval(() => {
this.bannerRight();
}, 3000);
},
bannerStyle(index) {
const { bannerIndex, banner } = this;
const base = 500;
let w = 0;
if (bannerIndex === index) {
w = 0;
}
// 最后一个index,且bannerIndex=0时
else if (bannerIndex === banner - 1 && index === 0) {
w = base;
}
// 第一个index,且bannerIndex=最后一个时
else if (bannerIndex === 0 && index === banner - 1) {
w = -base;
} else {
w = base * (index - bannerIndex);
}
return `transform: translateX(${w}px);`;
},
bannerLeft() {
this.bannerIndex2 = this.bannerIndex;
if (this.bannerIndex === 0) {
this.bannerIndex = this.banner - 1;
} else {
this.bannerIndex -= 1;
}
},
bannerRight() {
this.bannerIndex2 = this.bannerIndex;
if (this.bannerIndex === this.banner - 1) {
this.bannerIndex = 0;
} else {
this.bannerIndex += 1;
}
},
onClickDot(index) {
this.bannerIndex2 = this.bannerIndex;
this.bannerIndex = index;
},
},
};
</script>
<style scoped>
.banner {
width: 500px;
height: 300px;
overflow: hidden;
background: #f2f2f2;
position: relative;
}
.banner .img-box {
width: 500px;
height: 300px;
}
.banner .img-box .img-item {
width: 100%;
height: 100%;
line-height: 100%;
background: #d3dce6;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
.banner .img-box .img-item.active {
z-index: 2;
transition: 1s;
}
.arrows {
display: flex;
align-items: center;
justify-content: space-between;
position: absolute;
top: 50%;
left: 0;
width: 100%;
z-index: 9;
padding: 0 10px;
box-sizing: border-box;
transform: translateY(-50%);
}
.arrows div {
width: 30px;
height: 30px;
background: rgba(0, 0, 0, 0.1);
color: #fff;
font-size: 20px;
line-height: 30px;
border-radius: 50%;
text-align: center;
cursor: pointer;
}
.dots {
position: absolute;
bottom: 10px;
left: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
z-index: 9;
}
.dots span {
width: 10px;
height: 10px;
background: rgba(255, 255, 255, 0.4);
border-radius: 50%;
cursor: pointer;
margin: 0 10px;
}
.dots span.active {
background: #fff;
}
</style>