【知识归纳】浏览器光标及选区的获取和设置

本文已收录至博客《前端从入门到入土》,欢迎点赞、收藏 + 关注~

在使用 InputTextarea 的场景中,经常需要获取光标的位置或选择范围,以及设置光标的位置或选择范围。

获取光标位置

光标位置分为两种,数据层面的 Range,处于屏幕中的实际位置的 Position。我们先来说一下 Range

Range对象表示页面上的一个连续的文本范围或者一个节点范围。它包含了起始节点和结束节点,以及这两个节点之间的文本内容。

Range对象的数据结构如下所示:

typescript 复制代码
{
    startContainer: Node, // 范围的起始节点
    startOffset: number, // 范围在起始节点中的偏移量
    endContainer: Node, // 范围的结束节点
    endOffset: number, // 范围在结束节点中的偏移量
    commonAncestorContainer: Node // 范围的公共祖先节点
}

其中,startContainerendContainer 表示范围的起始节点和结束节点,可以是文本节点、元素节点等。startOffset endOffset 表示范围在起始节点和结束节点中的偏移量,即范围的起始位置和结束位置。commonAncestorContainer 表示范围的公共祖先节点,即起始节点和结束节点的最近共同父节点。

通过这些属性,可以对 Range 进行进一步的操作和处理,例如获取范围内的文本内容、插入新的节点等。

获取 Range

获取 Range 可以通过如下方法

js 复制代码
let selection = window.getSelection();
// 或者使用 let selection = document.getSelection();
if (selection.rangeCount > 0) {
  let range = selection.getRangeAt(0);
  // other code
}

获取选中的文本

js 复制代码
let range = selection.getRangeAt(0);
let textContent = range.toString();
console.log(textContent);

获取光标或选区位置

有时候我们希望获取光标或选区在屏幕中的位置,来做一些定位或特殊处理,可以在得到 Range 后,调用getBoundingClientRect来获取定位。

定位信息rect包含光标或选区在屏幕中的绝对定位。

js 复制代码
let range = selection.getRangeAt(0);
let rect = range.getBoundingClientRect();
console.log(rect);

如果我们希望能相对某个父元素进行定位,则同步调用父元素的dom.getBoundingClientRect,得到rect2,将两个值对应的定位信息相减,就能得到相对位置。

通过点击位置获取 Range

有时候我们可能希望通过点击位置获取一下点击后光标的位置。有两种方法可以实现。

  1. 遍历点击位置的元素,逐个查找哪个位置离点击位置最近。这里不详细讲解。
  2. 通过浏览器自带能力

当我们点击一个位置,在对应的 event 中,我们可以获取到点击位置的{x, y},此时可以调用下面的脚本,来获取Range

js 复制代码
if (document.caretRangeFromPoint) {
  domRange = document.caretRangeFromPoint(x, y);
} else {
  // @ts-ignore
  const position = document.caretPositionFromPoint(x, y);

  if (position) {
    domRange = document.createRange();
    domRange.setStart(position.offsetNode, position.offset);
    domRange.setEnd(position.offsetNode, position.offset);
  }
}

设置光标或选区

如果是<input><textarea>等可编辑元素,可以直接使用setSelectionRange

js 复制代码
let inputElement = document.getElementById('inputId');
let position = inputElement.value.length - 1; // 倒数第二个位置
inputElement.setSelectionRange(position, position);

如果不是<input><textarea>等可编辑元素,可以使用document.createRange()方法来创建一个Range对象,然后使用range.setStart()range.setEnd()方法来设置选区的起始和结束位置。最后,使用window.getSelection()方法获取当前的选区对象,并使用selection.removeAllRanges()方法清除之前的选区,再使用selection.addRange()方法将创建的Range对象添加到选区中,从而使选区生效。

js 复制代码
// 创建 Range 对象
let range = document.createRange();

// 设置 Range 对象的起始和结束位置
let startNode = document.getElementById('startNode');
let endNode = document.getElementById('endNode');
range.setStart(startNode, 0); // 设置起始位置,此处假设起始位置是节点的第一个字符
range.setEnd(endNode, 1); // 设置结束位置,此处假设结束位置是节点的第二个字符

// 获取当前的选区对象并添加 Range 对象
let selection = window.getSelection();
selection.removeAllRanges(); // 清除之前的选区
selection.addRange(range);

参考文档

  • GPT问答
相关推荐
烬羽3 小时前
给 Agent 一个检索式记忆:把对话历史存进 Milvus,该记的都记得
javascript·数据库·agent
磐链科技4 小时前
区块链开发入门实战:用 Hardhat 与 Ethers.js 搭建你的第一个 DApp
开发语言·javascript·区块链
码艺-Alimjan4 小时前
维吾尔语数字转文本
java·javascript·python·算法·go
可乐鸡翅yeah_4 小时前
hls.js 多实例并发踩坑,多视频页面播放器内存与冲突问题解决
开发语言·前端·javascript·音视频·hls·m3u8·m3u8在线播放
雪芽蓝域zzs4 小时前
第十四节:后端返回权限动态路由
前端·javascript·vue.js
小磊哥er4 小时前
Wonder Claude Code - 一个可运行的、教学级的 Claude Code 精简复刻
javascript·ai编程
bjzhang755 小时前
使用HTML+CSS美化上传进度条展示
前端·css·html
何以解忧,唯有..5 小时前
Vue 3 响应式核心:ref() 与 reactive() 的深入解析与实战
前端·javascript·vue.js
zzzzzz3106 小时前
看 react-bits,不要只看“酷炫”:一套阅读动画交互组件库的框架
javascript·react.js·动效
香芋芋圆14 小时前
AI 冲击内卷之下,普通前端如何破局?WebGIS—— 低门槛突围赛道
前端·javascript·人工智能·学习·职场发展