共计 2203 个字符,预计需要花费 6 分钟才能阅读完成。
声明:今天所分享的内容,都可以直接在控制台演示。
先来思考几个问题。
1. 我在一个页面中随意点了一下,没有留下任何痕迹。你能捕捉到我刚才点的是哪个节点,以及鼠标的落脚点在哪两个字之间吗(点击图片是无效的,本文只讨论文本的情况)?
2. 如何做到点击任意节点,选中并且复制任意一段文字呢?
3. 如何用脚本控制你用鼠标选中的区域呢(控制所选范围的大小,起始位置)?
上面三个问题,你能答出几道?这几个问题都是跟当前选择区域相关的知识点,这里我们合并在一起讲一下。先普及一些关于文本选择范围的基础知识。主要涉及到两个对象,Selection 和 Range。可以理解成 Selection 由 Range 组成,Selection 表示当前页面中鼠标选中的区域对象,可以用 window.getSelection() 来获取 Selection 对象,你可以用鼠标在当前页选取一个范围,然后打开控制台,输入 window.getSelection() 即可打印出 Selection 对象。可以调用 selection 的 toString 方法,结果就会打印出我们选择的文本内容。
let selection = window.getSelection();
console.log(selection.toString());
selection 有一个 rangeCount 属性,用来判断当前选择区域有多少个 range,重点来了:当进入一个网页,或者刷新当前页之后,如果你没有点击过任何地方,则 selection 的 rangeCount 值为 0,一旦你点击过任何地方,此时 rangCount 的值就变成了 1(此时你就可以打开控制台在控制台测试了)。所以这就可以用来判断当前页有没有被点击过。
let selection = window.getSelection();
if (selection.rangeCount == 0) {console.log('当前页面还没有被点击过');
} else {console.log('当前页面已经被点击过');
// 获取当前 selection 中的 range。(在网页中通过手动去选择范围只能有一个 range。用脚本可以实现 selection 中包含多个 range 的情况。)let range = selection.getRangeAt(0);
}
当我们知道当前页面被点击过之后,就可以来判断是哪个节点被点击了。点击了哪两个字的中间。此时就会用到几个 range 的属性,分别是 startContainer,endContainer,startOffset,endOffset. 先来看控制台打印出来的几个 range 的属性。
collapsed:表示当前 range 范围是否是闭合的。true 则表示当前 range 范围的起始和结束是同一个位置。其实就是当前页面上没有被选择的范围。也可以认为当前选择范围是一个点。commonAncestorContainer: 表示共同的祖先节点。如果当前选择范围是跨节点的,即我的开始点是在上一个 div,结束点在他的兄弟节点 div 中。那此时 commonAncestorContainer 就表示他俩的父节点(最近的公共祖先节点)。如果开始点和结束点在同一个 div 中,则此属性的值指向当前 div。startContainer/endContainer: 范围起始点和结束点所在的节点中。startOffset/endOffset: 范围起始点和结束点在当前 container 中的偏移量,即在 startContainer(或 endContainer) 中,起始点(或结束点)前面有多少个字。
结合上面的四个属性,我们就能轻易的找到刚才点击的哪个位置,(如果只是点击一下的话,collapsed 值为 true,startContainer 和 endContainer 相同,startOffset 和 endOffset 相等)到这里,我们开篇提到的第一个问题就解决了。
第一个问题理解了之后,后面的两个就变的很简单了。我们先来看第三个,只是用 range 的几个方法。设置一下 range 的边界值即可。
setStartAfter()
setStartBefore()
setEndAfter()
setEndBefore()
// 上面这四个方法是设置 range 范围的起始和结束位置的,参数传入节点即可。setStart()
setEnd()
// 上面这两个方法有两个参数,第一个传入节点,第二个传入偏移量,即从当前节点的第几个字开始。注意:这里的节点指的是文本节点(nodeType 是 3 的 text 节点)。
下面看第二个问题。首先选中一段文字,然后执行复制命令。
// 选中一段文字
let div = document.getElementById('div');
let selection = window.getSelection();
let range = document.createRange();
range.selectNode(div);
selection.removeAllRanges();
selection.addRange(range);
// 执行复制命令
document.execCommand('copy', false, null);
这里用到了一个很好用的方法,document.execCommand(),感兴趣的朋友自己下来查一下吧。
不管你是小哥哥还是小姐姐,觉得东西不错?给个赞再走吧!