最近接手了一个朋友的工作,她埋头考研去re。界面功能已经完善,只需要小改样式。组长让我加个轮播图,虽然市面上相关组件应有尽有,但我决定手写回顾一下这个经典功能٩(๑❛︶❛๑)۶
效果如下:
代码:
<section class="bg-common">
<div class="img-box" @mouseover="stop" @mouseleave="play">
<ul :style="containerStyle">
<li>
<img src="./images/3.jpg" alt="">
</li>
<li v-for="i in 3" :key="i">
<img :src="require('./images/'+i+'.jpg')" alt="">
</li>
<li>
<img src="./images/1.jpg" alt="">
</li>
</ul>
</div>
<div class="title-box">
<span>选你所爱</span>
<span>DO WHAT YOU LOVE</span>
</div>
<i class="el-icon-arrow-left left-arrow arrow" @click="slide(-1)"></i>
<i class="el-icon-arrow-right right-arrow arrow" @click="slide(1)"></i>
<div class="dot-box"><div v-for="i in 3" :key="i" @click="jump(i-1)" :class="{'dot-active':i===curIndex+1}"></div></div>
</section>
data() {
return {
timer: null,
curIndex: 1,
distance: -200
};
},
methods: {
slide(step) {
this.curIndex = (this.curIndex + 3 + step) % 3 //这里通过取模归整了一下数据,省却两个判断
const destination = this.distance - 100 * step
this.animate(destination, step)
},
jump(num) {
const step = num - this.curIndex
if(step!=0) this.slide(step)
},
animate(des, step) {
if((step > 0 && des < this.distance) || (step < 0 && des > this.distance)) {
this.distance -= 5 * step
window.setTimeout(() => {
this.animate(des, step)
}, 20)
} else {
this.distance = des
if (des < -300) this.distance = -100
if (des > -100) this.distance = -300
}
},
play() {
if (this.timer) {
this.stop()
}
this.timer = window.setInterval(() => {
this.slide(1)
}, 4000) //换图后停留4s
},
stop() {
window.clearInterval(this.timer)
this.timer = null
}
},
computed: {
containerStyle() {
return { transform: `translate3d(${this.distance}vw, 0, 0)`}
}
},
mounted() {
this.play()
window.onblur = function() { this.stop() }.bind(this)
window.onfocus = function() { this.play() }.bind(this)
}
<style lang="less" scoped>
section {
position: relative;
margin-top: 100px;
width: 100%;
height: 500px;
.img-box {
position: relative;
overflow: hidden;
height: 500px;
ul {
position: absolute;
display: flex;
padding: 0;
li>img {
width: 100vw;
flex-shrink: 0;
object-fit: cover;
}
}
}
.title-box {
position: absolute;
display: flex;
flex-direction: column;
align-items: center;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: aliceblue;
filter: brightness(110%);
span:nth-child(1) {
font-size: 54px;
font-weight: 800;
letter-spacing: 6px;
text-indent: 6px; //保持水平方向居中
margin-bottom: 20px;
}
span:nth-child(2) {
letter-spacing: 8px;
text-indent: 8px;
font-weight: 600;
}
}
.left-arrow {
left: 0;
}
.right-arrow {
right: 0;
}
.arrow {
position: absolute;
top: 50%;
transform: translateY(-50%);
color: aliceblue;
size: 30px;
font-weight: 600;
padding: 20px 16px;
background: rgba(0, 0, 0, 0.6);
transition: all .2s linear;
}
.arrow:hover {
padding: 20px;
background: rgba(0, 0, 0, 0.3);
}
.dot-box {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
justify-content: space-between;
width: 80px;
div {
width: 10px;
height: 10px;
border-radius: 10px;
background: rgba(255, 255, 255, 0.3);
}
}
}
.dot-active {
background: rgba(255, 255, 255, 0.8)!important;
}
</style>
总结:
学习了大佬的文章:Vue写一个图片轮播组件【转载】_51CTO博客_vue轮播组件
思路:
- 布局,灵活使用 absolute 和 flex 布局。
- 定时器实现简单轮播效果。
- 左右按键效果。
- 圆点定位。