React实现分段变速自动滚动与停止功能求助(TypeScript优先)
React长文本自动滚动控制实现(TypeScript)
核心实现思路
- 用
setInterval定时触发页面滚动,通过调整定时器间隔实现3档速度切换 - 维护滚动状态(是否滚动、当前速度档位),状态变化时动态创建/清除定时器
- 监听页面滚动位置,到达底部时自动停止滚动;同时监听用户手动滚动,触发停止逻辑
完整代码实现
import { useState, useEffect, useRef } from 'react'; // 定义三档速度的间隔时间(毫秒),数值越小滚动越快 const SPEED_LEVELS = [80, 40, 20]; // 每次滚动的像素步长 const SCROLL_STEP = 2; const LongTextReader = () => { const [speedLevel, setSpeedLevel] = useState<number>(0); const [isScrolling, setIsScrolling] = useState<boolean>(false); // 保存定时器引用,用于后续清除 const scrollTimerRef = useRef<NodeJS.Timeout | null>(null); // 开始滚动或切换速度 const handleStartScroll = () => { if (isScrolling) { // 切换到下一档速度 setSpeedLevel(prev => (prev + 1) % SPEED_LEVELS.length); // 清除旧定时器,后续useEffect会创建新的 scrollTimerRef.current && clearInterval(scrollTimerRef.current); } else { setIsScrolling(true); } }; // 停止滚动 const handleStopScroll = () => { setIsScrolling(false); scrollTimerRef.current && clearInterval(scrollTimerRef.current); scrollTimerRef.current = null; }; // 根据滚动状态和速度档位管理定时器 useEffect(() => { if (isScrolling) { scrollTimerRef.current = setInterval(() => { window.scrollBy(0, SCROLL_STEP); // 判断是否到达页面底部(预留10px误差) const isAtBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight - 10; if (isAtBottom) { handleStopScroll(); } }, SPEED_LEVELS[speedLevel]); } // 组件卸载或状态变化时清除定时器,避免内存泄漏 return () => { scrollTimerRef.current && clearInterval(scrollTimerRef.current); }; }, [isScrolling, speedLevel]); // 监听用户手动滚动,触发停止自动滚动 useEffect(() => { const handleManualScroll = () => { isScrolling && handleStopScroll(); }; window.addEventListener('scroll', handleManualScroll); return () => window.removeEventListener('scroll', handleManualScroll); }, [isScrolling]); return ( <div style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}> <div style={{ marginBottom: '20px' }}> <button onClick={handleStartScroll} style={{ padding: '8px 16px', marginRight: '10px' }} > {isScrolling ? `切换速度(当前${speedLevel + 1}档)` : '开始滚动'} </button> <button onClick={handleStopScroll} style={{ padding: '8px 16px' }} disabled={!isScrolling} > 停止滚动 </button> </div> {/* 示例长文本容器 */} <div style={{ lineHeight: '1.8' }}> {Array.from({ length: 100 }).map((_, i) => ( <p key={i}> 这是第{i + 1}段示例文本,用于模拟长文章或书籍内容。React应用中实现自动滚动功能,方便用户无需手动滚动即可阅读长文本内容。速度分为三档,点击开始按钮可以切换速度,到达底部或点击停止按钮时滚动停止。 </p> ))} </div> </div> ); }; export default LongTextReader;
关键细节说明
- 速度配置:
SPEED_LEVELS数组可按需调整,数值代表两次滚动的间隔时间;SCROLL_STEP控制每次滚动的像素距离 - 定时器管理:用
useRef存储定时器引用,确保在组件更新或卸载时能正确清除,避免内存泄漏 - 底部判断逻辑:通过对比窗口高度+滚动距离与文档总高度,判断是否到达底部,预留10px误差避免因浏览器兼容性导致的判断偏差
- 手动滚动拦截:监听用户的手动滚动操作,一旦触发立即停止自动滚动,保证交互的连贯性
内容的提问来源于stack exchange,提问作者Chuck-Chuck
相关产品推荐
相关产品推荐

