一、前言
最近刚好有个功能需要实现列表的无限循环滚动,在网上找到vue-seamless-scroll组件,使用起来很方便,也实现我需要的功能。我去查看了插件源码,实现原理还是比较有趣的,所以就参考了一下,自己手动实现个例子(有鼠标移入停止滚动,移出开始滚动功能)。
二、实现效果
三、功能分析
将一个 div 所有列表项包裹起来。用定时器控制 transform 来实现 div 自身的位移,代码中我是通过scrollTop参数开控制 y 方向的滚动,以此实现滚动的效果。关键在于将包裹列表的父元素设置 overflow: hidden; 属性。
<div class="scroll_list" :style="{ transform: `translate(0px,-${scrollTop}px)` }">
<div ref="scrollItemBox">
<div class="scroll_item" v-for="(item, index) in listData" :key="index">
{{item.title}}
</div>
</div>
<div v-html="copyHtml"></div>
</div>
动态控制 div 盒子的移动还是比较简单的,关键是无缝循环开始滚动,原理就是在所有列表项滚动完成后,将 div 的自身位移设置为0,也就是transform: translate(0px,0px)
,此时的移动是一瞬间的,所以肉眼是看不出来的。我的代码逻辑就是先获取所有列表项的高度,判断scrollTop是否大于等于列表的高度,如果大于等于,就将 scrollTop 设置为0。
this.scrollTop++
// 获取需要滚动的盒子的高度
let scrollItemBox = this.$refs.scrollItemBox.offsetHeight
// 当判断滚动的高度大于等于盒子高度时,从头开始滚动
if (this.scrollTop >= scrollItemBox) {
this.scrollTop = 0
}
由于列表一直滚动到最后,会出现短暂的区域空白,然后再从头开始滚动。解决这种问题也很简单,那就是在列表后面放一个一模一样的列表。如下实现。文章来源:https://www.toymoban.com/news/detail-607468.html
//在页面中
<div v-html="copyHtml"></div>
//获取列表的html并设置
this.copyHtml = this.$refs.scrollItemBox.innerHTML
鼠标移入停止,移出开始滚动就比较简单了,控制定时器就可以了。文章来源地址https://www.toymoban.com/news/detail-607468.html
// 鼠标移入停止滚动
mEnter() {
clearInterval(timer);
},
// 鼠标移出继续滚动
mLeave() {
this.startScroll()
},
// 开始滚动
startScroll() {
timer = setInterval(this.scroll, this.speed);
},
四、代码实现
<template>
<div class="InfiniteScroll">
<div class="scroll_parent_box" @mouseenter="mEnter" @mouseleave="mLeave">
<div class="scroll_list" :style="{ transform: `translate(0px,-${scrollTop}px)` }">
<div ref="scrollItemBox">
<div class="scroll_item" v-for="(item, index) in listData" :key="index">
{{item.title}}
</div>
</div>
<div v-html="copyHtml"></div>
</div>
</div>
</div>
</template>
<script>
let timer = null;
export default {
name: "InfiniteScroll",
data() {
return {
scrollTop: 0, //列表滚动高度
speed: 15, //滚动的速度
listData: [{
'title': '无缝滚动第一行',
}, {
'title': '无缝滚动第二行',
}, {
'title': '无缝滚动第三行',
}, {
'title': '无缝滚动第四行',
}, {
'title': '无缝滚动第五行',
}, {
'title': '无缝滚动第六行',
}, {
'title': '无缝滚动第七行',
}, {
'title': '无缝滚动第八行',
}, {
'title': '无缝滚动第九行',
},{
'title': '无缝滚动第十行',
},{
'title': '无缝滚动第十一行',
}], //表示有多少个列表项
copyHtml: '', //复制多一份防止滚动到后面出现空白
};
},
mounted() {
// 如果列表数据是异步获取的,记得初始化在获取数据后再调用
this.initScroll()
},
methods: {
initScroll() {
this.$nextTick(() => {
this.copyHtml = this.$refs.scrollItemBox.innerHTML
this.startScroll()
})
},
// 鼠标移入停止滚动
mEnter() {
clearInterval(timer);
},
// 鼠标移出继续滚动
mLeave() {
this.startScroll()
},
// 开始滚动
startScroll() {
timer = setInterval(this.scroll, this.speed);
},
// 滚动处理方法
scroll() {
this.scrollTop++
// 获取需要滚动的盒子的高度
let scrollItemBox = this.$refs.scrollItemBox.offsetHeight
// 当判断滚动的高度大于等于盒子高度时,从头开始滚动
if (this.scrollTop >= scrollItemBox) {
this.scrollTop = 0
}
}
},
};
</script>
<style scoped>
.InfiniteScroll {
box-sizing: border-box;
padding: 50px;
}
.scroll_parent_box {
width: 300px;
height: 400px;
border: 1px solid #ebeef5;
overflow: hidden;
box-sizing: border-box;
padding: 0 10px;
}
.scroll_list {
transition: all 0ms ease-in 0s
}
.scroll_item {
height: 40px;
line-height: 40px;
text-align: center;
font-size: 14px;
}
</style>
到了这里,关于vue非插件实现列表无限循环滚动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!