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

可滚动textarea文本剪切时滚动跳转问题及caret位置定位需求

解决方案

一、修复剪切/撤销重做后的滚动跳转问题

通过监听相关事件,手动保存恢复滚动位置并确保光标区域可见:

1. 处理剪切操作

const textarea = document.querySelector('textarea');

textarea.addEventListener('cut', (e) => {
  // 保存当前滚动位置与选区信息
  const scrollTop = textarea.scrollTop;
  const startPos = textarea.selectionStart;

  setTimeout(() => {
    // 恢复滚动位置
    textarea.scrollTop = scrollTop;
    // 重置光标到剪切后的正确位置
    textarea.selectionStart = textarea.selectionEnd = startPos;
    // 确保光标区域在视口内
    textarea.scrollIntoView({ block: 'nearest' });
  }, 0);
});

2. 处理撤销/重做操作

textarea.addEventListener('input', (e) => {
  if (['undo', 'redo'].includes(e.inputType)) {
    setTimeout(() => {
      const caretPos = textarea.selectionStart;
      // 创建范围获取光标位置的矩形信息
      const range = document.createRange();
      const sel = window.getSelection();
      range.setStart(textarea.childNodes[0], caretPos);
      range.setEnd(textarea.childNodes[0], caretPos);
      const caretRect = range.getBoundingClientRect();
      const textareaRect = textarea.getBoundingClientRect();

      // 计算滚动偏移,确保光标可见
      const topDiff = caretRect.top - textareaRect.top - textarea.clientTop;
      if (topDiff < 0) {
        textarea.scrollTop += topDiff;
      } else if (topDiff + caretRect.height > textarea.clientHeight) {
        textarea.scrollTop += topDiff + caretRect.height - textarea.clientHeight;
      }
    }, 0);
  }
});

二、获取光标所在的实际行(含自动换行)

利用元素矩形位置与行高计算实际行号(依赖固定行高配置):

function getCaretActualLine(textarea) {
  const caretPos = textarea.selectionStart;
  const lineHeight = parseInt(getComputedStyle(textarea).lineHeight);
  
  // 创建范围获取光标位置的垂直偏移
  const range = document.createRange();
  const sel = window.getSelection();
  range.setStart(textarea.childNodes[0], caretPos);
  range.setEnd(textarea.childNodes[0], caretPos);
  const caretRect = range.getBoundingClientRect();
  const textareaRect = textarea.getBoundingClientRect();
  
  // 计算实际行号(从1开始计数)
  const topOffset = caretRect.top - textareaRect.top;
  return Math.floor(topOffset / lineHeight) + 1;
}

// 使用示例
textarea.addEventListener('click', () => {
  console.log('光标所在实际行:', getCaretActualLine(textarea));
});

内容的提问来源于stack exchange,提问作者Elvis Murseli

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 11:03:31