需求:vue3实现一个div内的内容无限循环滚动
方法一:
<template>
<div id='container'>
<div class="item" v-for=item in 5>测试内容{
{
{ item }}</div>
</div>
</template>
<script setup>
//封装一个方法
const fengzhuang = (containerId) => {
let intervalId = null
const container = document.getElementById(containerId)
// console.log("container",container.scrollTop);
const content = container.scrollHeight
let containerHeight = container.clientHeight
let containerScrollTop = container.scrollTop
let currentScrollTop = 0;
const startScrolling = () => {
stopScrolling()
intervalId = setInterval(() => {
currentScrollTop += 1.5
if(currentScrollTop >= content - containerHeight){
currentScrollTop = 0
}
containerScrollTop = currentScrollTop;
container.scrollTop = containerScrollTop;
}, 50)
}
const stopScrolling = () => {
clearInterval(intervalId)
}
const checkOverflow = () => {
if (content > containerHeight) {
startScrolling()
} else {
stopScrolling()
}
}
checkOverflow()
}
//进入页面时执行这个方法
onMounted(()=> {
fengzhuang('container')
})
</script>
方法二:
<template>
<div id='container'>
<div id="content">
<div id="scrollWrapper">
<div class="item" v-for=item in 5>测试内容{
{
{ item }}</div>
</div>
</div>
</div>
</template>
<script setup>
//封装一个方法
let shouldScroll = ref(false)
const fengzhuang2 = (containerId,contentId,scrollWrapperId)=> {
const container = document.getElementById(containerId)
const content = document.getElementById(contentId)
const scrollWrapper = document.getElementById(scrollWrapperId)
const startScrolling = (scrollWrapper)=> {
const scrollSpeed = 0.01;
console.log("scrollWrapper.offsetHeight",scrollWrapper.offsetHeight);
const contentHeight = scrollWrapper.offsetHeight;
const containerHeight = container.offsetHeight;
// 设置初始滚动位置
scrollWrapper.style.transform = "translateY(0px)";
// 启动动画
scrollWrapper.animate([
{ transform: "translateY(0px)" },
{ transform: `translateY(-${contentHeight-320}px)` },
// { transform: `translateY(-${containerHeight}px)` },
], {
duration: (contentHeight + containerHeight) * scrollSpeed * 1000,
easing: "linear",
iterations: Infinity,
});
}
if (content.offsetHeight > container.offsetHeight) {
shouldScroll.value = true;
startScrolling(scrollWrapper);
}
}
//进入页面时执行这个方法
onMounted(()=> {
fengzhuang2('container','content','scrollWrapper')
})
</script>
方法三:
<template>
<div class="scroll-container">
<div class="scroll-content" :style="contentStyle">
<!-- 内容项 -->
<div v-for="(item, index) in items" :key="index" class="scroll-item" >
{
{ item }}
</div>
</div>
</div>
</template>
<script>
import { ref, onMounted, watchEffect } from "vue";
export default {
setup() {
const items = ref(["Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6"]); // 你的内容项数组
const containerHeight = 200; // 调整滚动容器的高度
const scrollSpeed = 0.5; // 调整滚动速度
const contentStyle = ref({
transform: "translateY(0)",
});
let currentIndex = 0;
const contentHeight = items.value.length * 40; // 假设每个项的高度为40px
const scrollFrame = () => {
currentIndex += scrollSpeed;
if (currentIndex >= contentHeight) {
currentIndex = 0;
}
// const itemToMove = items.value.slice(parseInt(currentIndex/40))
if(currentIndex % 40 == 0){
// const itemToMove = items.value.slice(currentIndex/40)[0]; // 弹出第一个元素
// const itemToMove = items.value.shift(); // 弹出第一个元素
console.log("itemToMove");
items.value.push(itemToMove); // 将弹出的元素放到数组末尾
}
contentStyle.value.transform = `translateY(-${currentIndex}px)`;
};
onMounted(() => {
// 每帧滚动
const scrollInterval = setInterval(scrollFrame, 15); // 16ms对应60帧每秒
// 当滚动容器高度改变时,重新计算当前位置以实现无缝滚动
watchEffect(() => {
// currentIndex = currentIndex % contentHeight;
contentStyle.value.transform = `translateY(-${currentIndex}px)`;
});
// 清除滚动定时器
return () => clearInterval(scrollInterval);
});
return {
items,
contentStyle,
};
},
};
</script>
<style scoped>
.scroll-container {
height: 40px; /* 调整滚动容器的高度 */
overflow: hidden;
border: 1px solid #ccc;
}
.scroll-content {
display: flex;
flex-direction: column;
animation: scroll 5s linear infinite; /* 5秒完成一次滚动,可根据需要调整 */
}
.scroll-item {
height: 40px; /* 每个滚动项的高度 */
line-height: 40px;
padding: 10px;
background-color: #f0f0f0;
}
@keyframes scroll {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-100%);
}
}
</style>
补充:el-table实现内容无限循环滚动方法:
let scrollHeight = 0
let currentScrollTop = 0
let maxScrollTop = 0
let timeInter = null
let timeInter2 = null
const tableNode = ref<any>(null)
function updateList() {
// 数据大于3条才会滑动
if (tableData && tableData.value.length > 4) {
// 获取滑动区域DOM 最新版本的element-plus节点有变化, 此版本为1.2.0-beta.3
tableNode.value = tableRef.value.$refs.bodyWrapper.getElementsByClassName('el-scrollbar__wrap')[0] // 设置每次滑动几行
scrollHeight = tableNode.value.querySelectorAll('tr')[0].offsetHeight * 4
// 设置每次滑动的PX和滑动区域的高度
tableNode.value.style.height = `${scrollHeight}px`
// 获取最大滑动空间
maxScrollTop = tableNode.value.firstElementChild.offsetHeight - scrollHeight
// 开始
restTimeInter()
}
}
function restTimeInter() {
// 清除所有定时器
clearAllInterval()
// 设置定时器
timeInter = setInterval(setMultiLine, 1500)
}
function clearAllInterval() {
clearInterval(timeInter)
clearInterval(timeInter2)
}
function setScrollTop() {
tableNode.value.scrollTop++
if (tableNode.value.scrollTop >= currentScrollTop) { // 达到下次应该滑动的位置
clearInterval(timeInter2)
}
if (tableNode.value.scrollTop > maxScrollTop) { // 滑到底了
tableNode.value.scrollTop = maxScrollTop
clearInterval(timeInter2)
}
}
function setMultiLine() {
// 下次应该滑到哪
currentScrollTop = (tableNode.value.scrollTop || 0) + scrollHeight + currentScrollTop % scrollHeight
if (tableNode.value.scrollTop >= maxScrollTop) { // 滑完了 重置
currentScrollTop = 0
tableNode.value.scrollTop = 0
restTimeInter()
} else {
// 清除上一个定时器
clearInterval(timeInter2)
// 开始滑
timeInter2 = setInterval(setScrollTop, 10)
}
}
onMounted(()=> {
setTimeout(() => {
updateList()
}, 1000)
})
以上三种方法均能实现无限循环滚动,但是滚动的效果不是无缝衔接的,是滚动到最底部后直接闪现到内容顶部开始重新滚动;要想实现无缝衔接滚动,目前用js是难以实现的,为此花费了好长时间也没能实现,最后在bd中查到了可以实现这一功能的插件,比如vue3-seamless-scroll插件,具体的插件安装和使用可自行百度;