需要哪些功能
- 可以无限滚动
- 可以自定义显示高度
- 可以自定义滚动速度
- 可以自定义滚动内容
遇到了哪些问题
- 滚动到最后一列后,过渡到头部时,会闪烁
实现
seamless-scroll.vue 组件
<script setup>
import { onMounted } from 'vue';
const props = defineProps({
list: {
type: Array,
required: true
},
// 每列移动的间隔
duration: {
type: Number,
default: 500
},
// 每列高度
itemHeight: {
type: Number,
required: true
},
// 可视高度
boxHeight: {
type: Number,
required: true
}
});
// 1.将数据复制一份放列表末尾
const lookSize = Math.round(props.boxHeight / props.itemHeight); // 可视个数
const listProp = [...props.list, ...props.list.slice(0, lookSize)];
// 设置容器宽高
const setHeight = () => {
const scroll = document.querySelector('.scroll-container').style;
scroll.setProperty('--boxHeight', `${props.boxHeight}px`);
scroll.setProperty('--itemHeight', `${props.itemHeight}px`);
};
const spriteFrames = [];
for (let index = 0; index <= props.list.length; index++) {
const obj = { transform: `translateY(-${index * props.itemHeight}px)` };
// 每次滚动一行
if (index === props.list.length) {
spriteFrames.push(obj);
} else {
// 添加相同帧,创造暂停效果
spriteFrames.push(obj, obj);
}
// 平滑滚动
// spriteFrames.push(obj);
}
console.log(spriteFrames);
// 添加移动事件
let boxAnimate; // 动画对象
const move = () => {
const box = document.querySelector('.scroll-box');
boxAnimate = box.animate(spriteFrames, {
duration: props.duration * listProp.length,
iterations: Infinity // 动画次数无限
});
};
// 暂停和启动
const mouseMove = () => {
const scroll = document.querySelector('.scroll-container');
scroll.onmouseover = () => {
boxAnimate.pause();
};
scroll.onmouseout = () => {
boxAnimate.play();
};
};
onMounted(() => {
setHeight();
move();
mouseMove();
});
</script>
<template>
<div class="scroll-container">
<div class="scroll-box">
<slot :listProp="listProp"></slot>
</div>
</div>
</template>
<style lang="scss" scoped>
.scroll-container {
--boxHeight: 0px;
--itemHeight: 0px;
height: var(--boxHeight);
line-height: var(--itemHeight);
overflow: hidden;
}
</style>
组件应用
<script setup>
import SeamlessScroll from '@/components/seamless-scroll/index.vue';
let list = [];
for (let index = 0; index < 10; index++) {
list.push({ title: `list${index}` });
}
</script>
<template>
<div class="list-container">
<SeamlessScroll
:list="list"
:duration="1000"
:item-height="30"
:box-height="30"
v-slot="{ listProp }"
>
<div v-for="(item, index) in listProp" :key="index">
{{ item.title }}
</div>
</SeamlessScroll>
</div>
</template>