可滚动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
相关产品推荐
相关产品推荐

