网上参考别人的代码改动的,原链接忘记是啥了,写这记一下(如果不妥,请评论说下)
<template>
<div class="swiper" ref="swiper" @click.prevent="handleClick">
<div
class="swiper-list"
:style="{width: swiperListWidth + 'px', transform: 'translateX(' + translateX + 'px)', transitionDuration: transitionDuration + 's' }"
ref="swiperList"
>
<div v-for="(item, i) in imgUrlList"
:style="{backgroundColor: item}"
:key="i"
:class="index === i ? 'current-item swiper-item' : 'swiper-item'"
@click="see(i)"
>
<img :src="item.url" alt="">
</div>
</div>
<!--<div class="dot">-->
<!--<span-->
<!--v-for="(x, i) in sum" :key="'dot' + x"-->
<!--:style="{background: i === index ? indicatorColor : 'rgba(255, 255, 255, .5)'}"-->
<!--:class="[i === index ? 'on': '']"-->
<!-->-->
<!--</span>-->
<!--</div>-->
<!--{{index}}-->
</div>
</template>
<script>
export default {
name: 'Test',
data () {
return {
swiperWidth: '', // 轮播图盒子的宽度
index: this.initialIndex, // 轮播图序号
sum: 4, // 轮播图片数量
transitionDuration: 0.5, // 切换动画时长
timer: '', // 定时器
startX: '', // touchstart的起始x坐标
offset: '', // move偏移值
Loop: 0,
imgList: ['red', 'bisque', 'blueviolet', 'royalblue'],
imgUrlList: [
{
url: 'https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2534506313,1688529724&fm=26&gp=0.jpg'
},
{
url: 'https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1208538952,1443328523&fm=26&gp=0.jpg'
},
{
url: 'https://dss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3386247472,87720242&fm=26&gp=0.jpg'
},
{
url: 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3252521864,872614242&fm=26&gp=0.jpg'
}
]
}
},
props: {
duration: {
type: Number,
default: 3000
},
initialIndex: {
type: Number,
default: 1
},
indicatorColor: {
type: String,
default: '#fff'
}
},
computed: {
// 轮播图列表的宽度
swiperListWidth () {
return this.swiperWidth * this.sum
},
// 轮播图列表偏移值
translateX () {
return this.index * this.swiperWidth * -1
}
},
created () {
this.$nextTick(() => {
let swiper = this.$refs.swiper
// 获得轮播图的图片数量
let swiperItems = document.querySelectorAll('.swiper-item')
this.sum = swiperItems.length
console.log(this.sum)
// 为什么不取屏幕宽度,是因为通用性,由外部的盒子决定轮播图的宽
this.swiperWidth = swiper.offsetWidth
// this.autoPlay()
// addEventListener不可以用匿名函数,因为无法解除绑定
swiper.addEventListener('touchstart', this.touchStart)
swiper.addEventListener('touchmove', this.touchMove)
swiper.addEventListener('touchend', this.touchEnd)
})
},
methods: {
see (i) {
this.index = i
},
autoPlay () {
this.timer = setInterval(() => {
let index = this.index + 1
// 取余数运算,0%5=0,1%5=1,5%5=0,当然用if判断语句也是可以的
this.index = index % this.sum
this.$emit('change', this.index)
}, this.duration)
},
touchStart (e) {
// 只记录第一根手指触发的值
clearInterval(this.timer)
this.transitionDuration = 0
this.startX = e.targetTouches[0].clientX
},
touchMove (e) {
this.offset = this.startX - e.targetTouches[0].clientX
this.$refs.swiperList.style.transform = `translateX(${this.translateX - this.offset}px)`
},
touchEnd () {
this.transitionDuration = 0.5
// 计算偏移值四舍五入,如果拖动距离大于等于0.5则换一张轮播图
let num = Math.round(this.offset / this.swiperWidth)
let sum = this.index + num
// 先计算再赋值给this.index避免重复触发计算属性,为什么这里不取余数,是因为又负数出现
if (sum > this.sum - 1) {
sum = this.sum - 1
} else if (sum < 0) {
sum = 0
}
// 解决拖动距离小于一半,index值无变化,无法触发计算属性,主动还原偏移值
if (sum === this.index) {
this.$refs.swiperList.style.transform = `translateX(${this.translateX}px)`
} else {
this.index = sum
this.$emit('change', this.index)
}
// 解决当第一次手势滑动后,再次点击offset不跟新问题
this.offset = 0
// this.autoPlay()
},
handleClick (e) {
e.preventDefault()
this.$emit('click', this.index)
}
},
// 实例销毁之前,移除绑定事件
beforeDestroy () {
let swiper = this.$refs.swiper
swiper.removeEventListener('touchstart', this.touchStart)
swiper.removeEventListener('touchmove', this.touchMove)
swiper.removeEventListener('touchend', this.touchEnd)
}
}
</script>
<style lang="less" scoped>
.swiper {
position: relative;
width: 100%;
height: 150px;
overflow: hidden;
.swiper-list {
display: flex;
align-items: center;
width: 100%;
height: 100%;
transition-property: all;
transition-timing-function: cubic-bezier(0.18, 0.89, 0.32, 1.28);
.swiper-item {
width: 120%;
height: 80%;
margin: 0 10px;
border-radius: 10px;
border: 1px solid rebeccapurple;
overflow: hidden;
img {
width: 100%;
height: 100%;
}
}
.current-item {
width: 95%;
height: 90%;
}
}
.dot {
display: flex;
position: absolute;
width: 100%;
margin-top: -15px;
justify-content: center;
span {
@size: 8px;
width: @size;
height: @size;
background-color: rgba(255, 255, 255, .5);
border-radius: 50%;
margin-left: 5px;
}
.on {
width: 12px;
border-radius: 30%;
transition: width 0.3s linear;
}
}
}
</style>
