You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 03:51:40