图一
图二
如图一所示,需求是比如在点击第四个选项时,会自动移至前方,并显示出下一个选项,到图二效果
由于scrollLeft 不是css中的属性,所以用css无法解决
思路:
将需要移动的距离均分,设置定时器每隔一段时间移动一点,直到 移动至目标距离为止,下面直接上代码
// html
<div class="scrollView" ref="idSwiperImg">
<div class="chooseImgItem" @click="tabClick(index)" v-for="(item, index) in normalData" :key="index" ref="imgList">
<van-image :src="item.pic[0].url" fit="cover" />
</div>
</div>
// scss
.scrollView {
width: 240px;
height: 78px;
overflow-x: scroll;
// 隐藏滚动条
&::-webkit-scrollbar {
display: none;
}
.chooseImgItem {
margin-left: 8px;
height: 56px;
width: 56px;
border-radius: 4px;
overflow: hidden;
.van-image {
width: 56px;
height: 56px;
}
&:first-child {
margin-left: 15px;
}
&:last-child {
margin-right: 15px;
}
}
}
// js
tabClick(index) {
// 容器宽度和内部点击的 item 宽度
let boxWidth = this.$refs.idSwiperImg.offsetWidth
let elWidth = this.$refs.imgList[index].offsetWidth
// 上一个选中的 item 下标 和 当前选中 item 下标
this.lastItemIndex = this.itemIndex
this.itemIndex = index
if (elWidth <= boxWidth / 3) {
// 获取当前容器的 scrollLeft 并计算接下去要移动的目标值
let distance = this.$refs.idSwiperImg.scrollLeft
let total = index * 70 - Math.floor( boxWidth / 3 )
// 上述两者的差值即为要移动的距离,将其细分为小块,确保为正值
let step = (distance - total) / 50
if (step < 0) step = -step
this.moveSlow(distance, total, step)
}
},
moveSlow(distance, total, step) {
// 正向滚动 和 反向滚动
if (this.lastItemIndex < this.itemIndex) {
// 每隔1毫秒移动一小段距离,直到移动至目标至为止,反之亦然
if (distance < total) {
distance += step
this.$refs.idSwiperImg.scrollLeft = distance
setTimeout(() => {
this.moveSlow(distance, total, step)
}, 1)
} else {
this.$refs.idSwiperImg.scrollLeft = total
}
} else if (this.lastItemIndex > this.itemIndex) {
if (distance > total) {
distance -= step
this.$refs.idSwiperImg.scrollLeft = distance
setTimeout(() => {
this.moveSlow(distance, total, step)
}, 1)
} else {
this.$refs.idSwiperImg.scrollLeft = total
}
}
}