Skip to content

无缝向上滚动组件

seamless-scroll.vue

jsx
<template>
	<view class="scroll-container" :style="{height: height + 'px'}">
		<view class="scroll-content" :style="{transform: 'translateY(-' + translateY + 'px)'}" ref="contentRef">
			<slot></slot>
		</view>
	</view>
</template>

<script setup>
	import {
		ref,
		onMounted,
		onUnmounted,
	} from 'vue';

	const props = defineProps({
		height: {
			type: Number,
			default: 400,
		},
		speed: {
			type: Number,
			default: 100,
		}
	});

	const translateY = ref(0); // Y轴位移
	let contentRef = ref(null);
	let contentHeight = 0;
	let previousTime = null;

	onMounted(() => {
		contentHeight = contentRef.value.$el.scrollHeight;
		startScroll();
	});

	onUnmounted(() => {
		cancelAnimationFrame(rafId);
	});

	let rafId;

	function startScroll() {
		function animateScroll(timestamp) {
			if (!previousTime) {
				previousTime = timestamp;
			}
			const elapsedTime = timestamp - previousTime;
			if (elapsedTime > 1000 / props.speed) {
				translateY.value += 1;
				if (translateY.value >= contentHeight - props.height) {
					translateY.value = 0;
				}
				previousTime = timestamp;
			}
			rafId = requestAnimationFrame(animateScroll);
		}
		rafId = requestAnimationFrame(animateScroll);
	}
</script>

<style scoped>
	.scroll-container {
		overflow: hidden;
	}
</style>
jsx
<template>
	<view class="scroll-container" :style="{height: height + 'px'}">
		<view class="scroll-content" :style="{transform: 'translateY(-' + translateY + 'px)'}" ref="contentRef">
			<slot></slot>
		</view>
	</view>
</template>

<script setup>
	import {
		ref,
		onMounted,
		nextTick
	} from 'vue';

	const props = defineProps({
		height: {
			type: Number,
			default: 200,
		},
		speed: {
			type: Number,
			default: 150,
		}

	})
	// 容器高度
	const translateY = ref(0); // Y轴位移
	const items = ref([]); // 列表项
	let contentRef = ref(null);
	let contentHeight = 0;

	onMounted(async () => {
		await nextTick(); // 等待组件渲染完成
		contentHeight = contentRef.value.$el.scrollHeight;
		startScroll();
	});

	function startScroll() {
		setInterval(() => {
			translateY.value += 1;
			if (translateY.value >= contentHeight - props.height) {
				translateY.value = 0;
			}
		}, 1000 / props.speed);
	}
</script>

<style scoped>
	.scroll-container {
		overflow: hidden;
	}

	.scroll-content {
		animation: scrollAnimation infinite linear;
	}

	@keyframes scrollAnimation {
		from {
			transform: translateY(0);
		}

		to {
			transform: translateY(-100%);
		}
	}
</style>

使用

jsx
<seamless-scroll :height="200" :speed="10">
			<view v-for="(item, index) in items" :key="index" class="scroll-item h-100px">{{ item }}</view>
		</seamless-scroll>