react实现无缝自动滚动
实现无缝自动滚动的核心思路
利用setInterval或requestAnimationFrame控制滚动位置,当内容滚动到末尾时无缝衔接至开头,视觉上形成无限循环效果。
关键代码结构
import React, { useRef, useEffect } from 'react';
const AutoScrollList = ({ items, speed = 50 }) => {
const containerRef = useRef(null);
const contentRef = useRef(null);
useEffect(() => {
const container = containerRef.current;
const content = contentRef.current;
let scrollPos = 0;
let animationId;
const scroll = () => {
scrollPos += 1;
if (scrollPos >= content.scrollHeight / 2) {
scrollPos = 0;
}
container.scrollTop = scrollPos;
animationId = requestAnimationFrame(scroll);
};
animationId = requestAnimationFrame(scroll);
return () => cancelAnimationFrame(animationId);
}, []);
return (
<div ref={containerRef} style={{ overflow: 'hidden', height: '200px' }}>
<div ref={contentRef}>
{[...items, ...items].map((item, index) => (
<div key={index}>{item}</div>
))}
</div>
</div>
);
};
实现细节说明
克隆数据实现无缝衔接
通过渲染双份数据([...items, ...items]),当滚动到中间位置时重置scrollTop,视觉上无跳跃感。

性能优化
使用requestAnimationFrame替代setInterval确保动画流畅性,组件卸载时清除动画帧。
样式要求
外层容器需固定高度并设置overflow: hidden,内层高度自适应。

扩展功能
动态速度控制
通过speed参数调整滚动速度,修改scrollPos的增量即可:
scrollPos += speed / 10; // 根据speed参数动态调整
暂停与继续
添加状态控制滚动启停:
const [isPaused, setIsPaused] = useState(false);
useEffect(() => {
// ...原有逻辑...
if (!isPaused) animationId = requestAnimationFrame(scroll);
}, [isPaused]);
注意事项
- 确保内容高度大于容器高度,否则无需滚动。
- 移动端需考虑触摸事件冲突,可通过
touch-action: none禁用默认触摸行为。 - 大量数据时需配合虚拟滚动优化性能。





