Selection 对象表示用户选择的文本范围或插入符号的当前位置。它代表页面中的文本选区,可能横跨多个元素。文本选区由用户拖拽鼠标经过文字而产生。要获取用于检查或修改的Selection对象,请调用 window.getSelection()。Range,表示包含节点和部分文本节点的文档片段,可以通过 Selection 对象的 getRangeAt 方法取得,也可以通过 Document 对象的 createRange 方法创建。
在我们日常前端开发中,可能会遇到这样的场景,实现划词翻译、点击取词翻译、编辑器中的复制、粘贴等需求,下面我们通过对这两种需求场景来介绍 Selection 对象 和 Range 对象在实际项目中的应用。
应用一:实现点击取词并翻译
实现基本思路,点击时获取 Selection 对象,并创建选取,通过 Range 的 setStart 和 setEnd 方法扩大文档片段的范围,以空格或者特殊符号为临界状态,终止循环。
1.方法一实现相关逻辑如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| if (window.getSelection) { let selection, range, node, start, end, text, rect, isFun, isText;
isFun = !!window.JSInvoker && typeof window.JSInvoker.toggleWordTooltip === 'function';
isText = function (text) { return text && /^[a-zA-Z]+$/.test(text); }
isFun && window.JSInvoker.toggleWordTooltip(false);
selection = window.getSelection(); range = selection.getRangeAt(0); node = selection.anchorNode; start = range.startOffset; end = range.endOffset; text = range.toString();
while (!/^\s+/.test(text)) { if (start === 0) { range.setStart(node, start); text = range.toString(); break; } else { start -= 1; range.setStart(node, start); text = range.toString(); } if (!isText(text)) { start += 1; range.setStart(node, start); text = range.toString(); break; } } while (!/\s+$/.test(text)) { if (end === node.length) { range.setEnd(node, end); text = range.toString(); break; } else { end += 1; range.setEnd(node, end); text = range.toString(); } if (!isText(text)) { end -= 1; range.setEnd(node, end); text = range.toString(); break; } }
rect = range.getBoundingClientRect(); text = text.trim(); if (isText(text) && isFun && rect) { window.JSInvoker.toggleWordTooltip(true, text, rect.x, rect.y, rect.width, rect.height); } else { alert(`Text: ${text}, isFun: ${isFun}, Rect: ${JSON.stringify(rect)}`); } } else { }
|
ps: 文本选中颜色可以通过 CSS3 ::selection 来实现,但是兼容性是个问题,可以通过 rect 属性值来创建个 mask 浮层 position:absolute;
来实现
2.方法二实现方案比较简单,实现代码逻辑如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| if (window.getSelection) { let selection, start, end, word;
selection = window.getSelection();
selection.modify('extend', 'backward', 'word'); start = selection.toString();
selection.modify('extend', 'forward', 'word'); end = selection.toString();
selection.modify('move', 'forward', 'character');
word = start + end; alert(`Selected Text: ${word}`); } else { }
|
应用二:实现划词翻译
1.获取划词文本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function getSelected () { let selection; if (window.getSelection) { selection = window.getSelection(); } else if (document.getSelection) { selection = document.getSelection(); } else if (document.selection) { selection = document.selection.createRange().text; }
return selection.toString().trim(); }
|
2.清空选中文本
1 2 3 4 5 6 7 8 9
| function removeSelection () { if (window.getSelection) { window.getSelection().removeAllRanges(); } else if (document.getSelection && document.getSelection.empty) { document.getSelection().empty(); } else if (document.selection && document.selection.empty) { document.selection.empty(); } }
|
第三方库
rangy A cross-browser JavaScript range and selection library.
转载申请
本作品采用知识共享署名 4.0 国际许可协议进行许可,转载时请注明原文链接,文章内图片请保留全部内容。