1、index.vue
<template>
<div class="page-content">
<swiper :autoPlay="false">
<swiper-item v-for="i in 4" :key="i">
<div
class="cust"
:style="{
backgroundColor: `#${colors[i - 1]}`
}"
>{{i}}</div>
</swiper-item>
</swiper>
</div>
</template>
<script>
import swiper from './swiper.vue';
import swiperItem from './swiper-item.vue';
export default {
name: 'Announcement',
components: {
swiper,
swiperItem
},
data() {
return {
colors: ['e71dba', '87eb86', 'e14723', 'd3d72f']
};
}
};
</script>
<style lang="less" scoped>
.page-content {
display: flex;
justify-content: center;
.cust {
text-align: center;
border: 1px solid;
width: 400px;
height: 300px;
line-height: 300px;
}
}
</style>
2、swiper.vue
<template>
<div class="swiper-content" :style="{
height: `${height}px`,
width: `${width}px`
}">
<div @click="clickHandle('pre')" class="swiper-btn-content swiper-btn-content_left">
<slot name="leftBtn">
<div class="swiper-btn left-btn"></div>
</slot>
</div>
<div @click="clickHandle('next')" class="swiper-btn-content swiper-btn-content_right">
<slot name="rightBtn">
<div class="swiper-btn right-btn"></div>
</slot>
</div>
<slot></slot>
</div>
</template>
<script>
export default {
name: 'swiper',
props: {
height: {
type: Number,
default: 300
},
width: {
type: Number,
default: 400
},
intervalTime: {
type: Number,
default: 1500
},
autoPlay: {
type: Boolean,
default: true
}
},
data() {
return {
changeType: '',
active: 0,
interval: null,
slotsLength: 0
};
},
mounted() {
if (this.$slots && this.$slots.default) {
this.slotsLength = this.$slots.default.length;
this.initSwiper(this.active);
if (this.autoPlay) {
this.interval = setInterval(() => {
this.changeType = 'next';
if (this.active >= this.slotsLength - 1) {
this.active = 0;
} else {
this.active++;
}
}, this.intervalTime);
}
}
},
destroyed() {
if (this.autoPlay) {
clearInterval(this.interval);
}
},
watch: {
active(val) {
this.initSwiper(val);
}
},
methods: {
initSwiper(active) {
for (let i = 0, s = this.$slots.default; i < s.length; i++) {
s[i].elm.style.transition = '';
if (i === active + 1) { // 此时将要展示的item的后一个
if (this.changeType === 'pre') {
s[i].elm.style.transition = 'transform .5s ease-in-out';
}
s[i].elm.style.transform = `translateX(${this.width}px) scale(1)`;
} else if (i === active - 1) { // 此时将要展示的item的前一个
s[i].elm.style.transition = 'transform .5s ease-in-out';
s[i].elm.style.transform = `translateX(-${this.width}px) scale(1)`;
} else if (active === s.length - 1 && i === s.length - 1) { // 当前展示:最后一个item
s[0].elm.style.transform = `translateX(${this.width}px) scale(1)`;
s[i].elm.style.transition = 'transform .5s ease-in-out';
s[i].elm.style.transform = `translateX(0px) scale(1)`;
} else if (i !== active + 1 && i !== active - 1 && i !== active) { //其他 不等于当前展示的item
if (!active && i === s.length - 1) { // 当前展示:第一个item,则需要对最后一个进行特殊设置
s[s.length - 1].elm.style.transition = 'transform .5s ease-in-out';
s[s.length - 1].elm.style.transform = `translateX(-${this.width}px) scale(1)`; // 最后一个item
} else if (active === s.length - 1 && !i) { // 如果是 倒序轮播时,此时将要展示的是最后一个, 第一个item即将向右隐藏时
s[0].elm.style.transition = 'transform .5s ease-in-out';
s[0].elm.style.transform = `translateX(${this.width}px) scale(1)`;
} else {
s[i].elm.style.transform = `translateX(-${this.width * (s.length - 1)}px) scale(1)`;
}
} else {
s[i].elm.style.transition = 'transform .5s ease-in-out';
s[i].elm.style.transform = `translateX(0px) scale(1)`;
}
}
},
clickHandle (type) {
if (type === 'pre') {
this.changeType = 'pre';
if (this.active > 0) {
this.active--;
} else {
this.active = this.slotsLength - 1;
}
} else {
this.changeType = 'next';
if (this.active < this.slotsLength - 1) {
this.active++;
} else {
this.active = 0;
}
}
}
}
};
</script>
<style lang="less" scoped>
.swiper-content {
position: relative;
overflow: hidden;
.swiper-btn-content {
position: absolute;
min-width: 36px;
min-height: 36px;
z-index: 9;
transform: translateY(-50%);
top: 50%;
.swiper-btn {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
width: 36px;
height: 36px;
color: #FFFFFF;
font-size: 12px;
cursor: pointer;
border-radius: 50%;
background-color: rgba(31, 45, 61, .11);
transition: .5s;
&:hover {
background-color: rgba(31, 45, 61, .34);
}
}
.left-btn {
left: 5px;
&::before {
content: '<';
}
}
.right-btn {
right: 5px;
&::before {
content: '>';
}
}
&_left {
left: 5px;
}
&_right {
right: 5px;
}
}
}
</style>
3、swiper-item.vue
<template>
<div class="item">
<slot></slot>
</div>
</template>
<script>
export default {
name: 'swiperItem'
};
</script>
<style lang="less" scoped>
.item {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
</style>
网友评论