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

ReactJS打字测试Web应用实现div自动滚动方案咨询

实现React打字测试应用的自动滚动功能

核心思路

通过监听用户输入文本的变化,获取当前光标所在元素的位置,对比滚动容器的可见区域边界,自动调整容器的滚动位置,确保光标始终处于用户可见范围内。

修改TextDisplay组件

  1. 添加引用(Ref):使用useRef获取滚动容器和当前光标元素的DOM引用
  2. 监听输入变化:使用useEffect在typedText更新时,计算光标与容器的位置差并调整滚动

修改后的完整代码:

import React, { useRef, useEffect } from 'react'

export default function TextDisplay({givenText, typedText}) {
  const containerRef = useRef(null);
  const cursorRef = useRef(null);
  let typedArray = typedText.split('');
  let givenArray = givenText.split('');

  useEffect(() => {
    if (!cursorRef.current || !containerRef.current) return;

    const container = containerRef.current;
    const cursor = cursorRef.current;

    const containerRect = container.getBoundingClientRect();
    const cursorRect = cursor.getBoundingClientRect();

    // 计算光标与容器可见区域的位置偏移量
    const bottomOffset = cursorRect.bottom - containerRect.bottom;
    const topOffset = cursorRect.top - containerRect.top;

    // 根据偏移量自动调整滚动位置
    if (bottomOffset > 0) {
      container.scrollTop += bottomOffset;
    } else if (topOffset < 0) {
      container.scrollTop += topOffset;
    }
  }, [typedText]);

  return (
      <div 
        ref={containerRef}
        className='text-justify w-4/5 sm:w-3/5 text-base sm:text-lg md:text-xl lg:text-2xl h-full overflow-y-auto p-1'
      >
          {givenArray.map((val, ind) => {
              if (val == typedArray[ind] && ind < typedArray.length) {
                  return (
                    <div 
                      ref={ind === typedArray.length - 1 ? cursorRef : null}
                      key={ind} 
                      className={`${ind === typedArray.length - 1 ? 'border-r-2' : ''} ${typedArray.length === 0 && ind === 0? 'border-l-2' : ''} character inline border-purple-500 text-purple-700`}
                    >
                      {val}
                    </div>
                  )
                } else if(val !== typedArray[ind] && ind < typedArray.length){
                  return (
                    <div 
                      ref={ind === typedArray.length - 1 ? cursorRef : null}
                      key={ind} 
                      className={`${ind === typedArray.length - 1 ? 'border-r-2' : ''} ${typedArray.length === 0 && ind === 0? 'border-l-2' : ''} character inline border-purple-500 ${val===' '?'underline decoration-red-500':'text-red-500'}`}
                    >
                      {val}
                    </div>
                  )
              } else {
                  return (
                    <div 
                      ref={typedArray.length === 0 && ind === 0 ? cursorRef : null}
                      key={ind} 
                      className={`${ind === typedArray.length - 1 ? 'border-r-2' : ''} ${typedArray.length === 0 && ind === 0? 'border-l-2' : ''} character inline border-purple-500 text-slate-400`}
                    >
                      {val}
                    </div>
                  )
              }
          })}
      </div>
  )
}

方案优势

  • 无需拆分文本段落,适配任意长度的输入内容
  • 基于DOM元素实际位置计算滚动,自动适配不同屏幕尺寸和字体大小
  • 同时支持输入前进和退格操作时的滚动调整,全程保证光标可见

内容的提问来源于stack exchange,提问作者Shubham Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:34:50