组件内容
<template>
<div class="bannerBox" :style="imgStyle" @mouseover="stopAuto" @mouseout="autoPlayFunc">
<div class="bannerList" :style="bannerListStyle">
<img :src="imgList[imgList.length-1]" :style="imgStyle" />
<img v-for="imgOne in imgList" :key="imgOne" :src="imgOne" :style="imgStyle" />
<img :src="imgList[0]" :style="imgStyle" />
</div>
<div class="banner-direction" v-show="show">
<span class="banner-left" @click="toLeft"><</span>
<span class="banner-right" @click="toRight">></span>
</div>
<div class="banner-dots">
<button
v-for="(item,index) in imgList.length"
:key="index"
:class="{active:index==dotsIndex}"
@click="toDots(index)"
></button>
</div>
</div>
</template>
<script>
let interval = null,
timeout = null;
export default {
name: "banner",
props: {
width: {
//图片的宽度
type: Number,
default: 500,
},
height: {
//图片的高度
type: Number,
default: 300,
},
interval: {
//自动切换时间间隔
type: Number,
default: 5000,
},
duration: {
//滑动动画时长
type: Number,
default: 3000,
},
imgList: {
//图片列表
type: Array,
default: [],
},
current: {
//当前所在滑块的index
type: Number,
default: 0,
},
autoPlay: {
//是否自动播放
type: Boolean,
default: true,
},
},
data() {
return {
currentDuration: this.duration,
imgIndex: this.current,
dotsIndex: this.current - 1,
show: false,
};
},
created() {
if (this.autoPlay) {
this.autoPlayFunc();
}
},
computed: {
imgStyle() {
return {
width: this.width + "px",
height: this.height + "px",
};
},
bannerListStyle() {
const currentDuration = this.currentDuration;
const currentLeft = -this.imgIndex * this.width + "px";
console.log(currentLeft);
return {
width: this.width * (this.imgList.length + 2) + "px",
height: this.height + "px",
transition: "all " + currentDuration + "ms",
"-moz-transition": "all " + currentDuration + "ms",
"-webkit-transition": "all " + currentDuration + "ms",
"-o-transition": "all " + currentDuration + "ms",
transform: "translateX(" + currentLeft + ")",
"-moz-transform": "translateX(" + currentLeft + ")",
"-webkit-transform": "translateX(" + currentLeft + ")",
"-o-transform": "translateX(" + currentLeft + ")",
};
},
},
destroyed() {
clearInterval(interval);
clearTimeout(timeout);
},
methods: {
stopAuto() {
clearInterval(interval);
clearTimeout(timeout);
this.show = true;
},
autoPlayFunc() {
clearInterval(interval);
this.show = false;
interval = setInterval(() => {
this.toRight();
}, this.interval);
},
toRight() {
if (this.imgIndex == this.imgList.length) {
this.currentDuration = 0;
this.imgIndex = 0;
this.dotsIndex = 0;
clearTimeout(timeout);
timeout = setTimeout(() => {
this.$nextTick(function () {
this.currentDuration = this.duration;
this.imgIndex++;
});
}, 30);
} else {
this.imgIndex++;
this.dotsIndex++;
}
},
toLeft() {
if (this.imgIndex == 1) {
this.currentDuration = 0;
this.imgIndex = this.imgList.length + 1;
this.dotsIndex = this.imgList.length - 1;
clearTimeout(timeout);
timeout = setTimeout(() => {
this.$nextTick(function () {
this.currentDuration = this.duration;
this.imgIndex--;
});
}, 30);
} else {
this.imgIndex--;
this.dotsIndex--;
}
},
toDots(index) {
this.dotsIndex = index;
this.imgIndex = index + 1;
},
},
};
</script>
<style scoped>
.bannerBox {
position: relative;
overflow: hidden;
}
.bannerList {
position: absolute;
top: 0;
left: 0;
width: 1500px;
height: 300px;
}
.bannerList img {
float: left;
}
.banner-direction {
position: absolute;
top: 50%;
transform: translateY(-50%);
-moz-transform: translateY(-50%); /* Firefox */
-webkit-transform: translateY(-50%); /* Safari 和 Chrome */
-o-transform: translateY(-50%); /* Opera */
width: 100%;
}
.banner-left,
.banner-right {
width: 40px;
height: 40px;
line-height: 40px;
text-align: center;
color: #ffffff;
background: rgba(0, 0, 0, 0.3);
}
.banner-left {
float: left;
}
.banner-right {
float: right;
}
.banner-dots {
position: absolute;
bottom: 10px;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.banner-dots button {
width: 10px;
height: 10px;
border-radius: 50%;
margin: 0 5px;
padding: 0;
background: #ccc;
border: none;
}
.banner-dots .active {
background: #ff5500;
}
</style>
引用组件
<template>
<div>
<vue-banner :width="400" :height="200" :interval="3000" :duration="1000" :imgList=imgList :current="2"></vue-banner>
</div>
</template>
<script>
import VueBanner from "@/components/vue-banner/banner";
export default {
name: "banner",
data() {
return {
imgList: [
"http://lorempixel.com/640/480/nature",
"http://lorempixel.com/640/480/technics"
],
};
},
components: { VueBanner },
};
</script>
<style scoped>
</style>