轮播图模块(vue)
通过属性方式传值
值为一个数组、每一项含有imgUrl(图片地址)、link(跳转链接),link为可选属性
<template>
<div class="createBannerArea">
<!-- 图片区域 -->
<div class="imgArea" ref="imgArea" style="marginLeft:0" @mouseenter="onMouseenter" @mouseleave="onMouseleave">
<template v-if="arrUrl[0].link">
<a v-for="(item,index) in arrUrl" :key="index" href="item.link">
<img :src=item.imgUrl :alt="item.imgUrl" srcset="">
</a>
<a href="arrUrl[0].link">
<img :src=arrUrl[0].imgUrl alt="" srcset="">
</a>
</template>
<template v-else>
<img v-for="(item,index) in arrUrl" :key="index" :src=item.imgUrl alt="" srcset="">
<img src=arrUrl[0].imgUrl alt="" srcset="">
</template>
</div>
<!-- 小圆圈 -->
<div class="circleArea">
<span ref="circle" v-for="(item,index) in arrUrl" :key="index" @click="onClick(index)"></span>
</div>
</div>
</template>
<script>
export default {
name: 'createBannerArea',
data(){
return {
timer1: null, // 图片切换定时器
timer2: null, // 图片过渡定时器
time1: 2000, // timer1定时器的时间
time2: 10, // timer2定时器的时间
time3: 500, // 多久完成过渡
index: 0, // 当前显示第几张
circleColor: '#ddd', // 圆圈颜色
activeCirclecolor: '#aaa', // 选中状态时圆圈颜色
}
},
props: {
arrUrl: {
type: Array,
default: function(){
return []
}
}
},
methods: {
onMouseenter(){
clearInterval(this.timer1)
this.timer1 = null
},
onMouseleave(){
this.autoChange()
},
onClick(index){
this.index = index
this.setStatus();
this.autoChange();
},
// 轮播
autoChange(){
if(this.timer1){
clearInterval(this.timer1);
this.timer1 = null
}
this.timer1 = setInterval(() => {
if(this.index == this.arrUrl.length){
this.index = 1;
}else{
this.index ++
}
this.setStatus()
}, this.time1);
},
// 设置动画
setStatus(){
for(var i = 0; i < this.arrUrl.length; i++){
if(i == this.index){
this.$refs.circle[i].style.backgroundColor = this.activeCirclecolor;
}else{
this.$refs.circle[i].style.backgroundColor = this.circleColor;
}
if(this.index === this.arrUrl.length){
this.$refs.circle[0].style.backgroundColor = this.activeCirclecolor;
}
}
var start = parseInt(this.$refs.imgArea.style.marginLeft);
var end = -this.index * 100;
var dis = end - start;
var speed = dis / this.time3;
if(this.timer2){
clearInterval(this.timer2);
this.timer2 = null
}
this.timer2 = setInterval(() => {
start += speed * this.time2;
this.$refs.imgArea.style.marginLeft = start + '%';
if(Math.abs(end - start) < 1){
if(this.index == this.arrUrl.length){
this.$refs.imgArea.style.marginLeft = 0 + '%';
}else{
this.$refs.imgArea.style.marginLeft = end + '%';
}
clearInterval(this.timer2);
this.timer2 = null
}
}, this.time2);
},
// 清除定时器
clearTimer(){
clearInterval(this.timer1);
clearInterval(this.timer2);
},
onVisibilitychange(){
document.addEventListener("visibilitychange", this.isDocuHidden)
},
// 判断页面是hidden还是visible状态,目的是当最小化和切换其他标签页时,停止定时器,优化性能
// visible: 页面内容至少是部分可见。 在实际中,这意味着页面是非最小化窗口的前景选项卡。
// hidden: 页面内容对用户不可见。 在实际中,这意味着文档可以是一个后台标签,或是最小化窗口的一部分,或是在操作系统锁屏激活的状态下。
isDocuHidden(){
if(document.visibilityState == 'hidden'){
this.clearTimer()
}else if(document.visibilityState == 'visible'){
this.autoChange();
}
}
},
beforeDestroy(){
// 当组件销毁前清除定时器和document的事件
this.clearTimer()
document.removeEventListener('visibilitychange',this.isDocuHidden)
},
mounted: function () {
this.$nextTick( () => {
this.autoChange()
this.onVisibilitychange();
})
}
}
</script>
<style scoped>
.createBannerArea{
100%;
height: 500px;
overflow: hidden;
outline: 1px solid red;
margin: 10px auto;
}
.createBannerArea .imgArea{
display: flex;
flex-wrap: nowrap;
100%;
height: 100%;
}
.createBannerArea .imgArea a{
flex: 0 0 auto;
100%;
height: 100%;
}
.createBannerArea .imgArea img{
100%;
height: 100%;
}
.circleArea{
margin-top: -25px;
text-align: center;
}
.circleArea span{
display: inline-block;
10px;
height: 10px;
margin: 0 10px;
border-radius: 50%;
background-color: #999;
cursor: pointer;
}
.circleArea span:first-child{
background-color: #777;
}
</style>