声明:今天所分享的内容,都可以直接在控制台演示。
先来思考几个问题。
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(),感兴趣的朋友自己下来查一下吧。
不管你是小哥哥还是小姐姐,觉得东西不错?给个赞再走吧!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。