编辑器基本思路
一、contentEditable
div的contentEditable属性可以让div进入编辑模式,禁止可以使用contentEditable=false。
二、Selection
浏览器中内置了获取用户操作的方法:
let selection = window.getSelection();
Selection 对象有anchorNode和focusNode属性,可以用来获得选中部分的开始和结束元素,不过一般会用Range代替。还有一个isCollapsed属性,为true时,代表选择区域开始和结束在相同的点,也就是没有选中内容时光标闪烁的模式。修改选择范围,主要就是对Range对象进行编辑。首先可以通过:
let range = selection.getRangeAt(0);
获取被选中的第一个区块,以此类推往后选。
获得了Range对象,就可以获得选中区域内容了。
Range对象获得选择区域的开始和结束点:
range.startContainer //开始点所在的容器(元素)
range.endOffset // 开始点在其容器内的偏移
range.endContainer // 结束点所在的容器(元素)
range.endOffset // 结束点在其容器内的偏移
还有一个非常有用的属性:
range.commonAncestorContainer // 选择范围的共同父元素
需要注意的是,返回的Range对象是可变对象。
简单来说,如果用户的选区改变了,那么Range对象的内容也会改变。因此要记录某一时刻的Range,就要记录。
此外,Range对象还定义了各种获取内容和修改内容的函数,详见文档,这里只是一些常用的。
1) 获得选取的坐标范围
可以获得光标在网页上的精确位置,获得光标的位置或者选区的矩形边框可以使用:
let rect = range.getBoundingClientRect();
rect对象包括的属性包括矩形的top、left、right、bottom坐标。如果选取是collapsed的话,这四个属性就可以用来计算光标的位置。
2) 保存选区并恢复
如果对选择区域内的元素进行了修改,比如添加新元素、改变元素类型等等,那么原来的选区会失效。因此一个比较有用的技巧就是在修改元素之前,先保存选区Range,待修改完成后再恢复:
let selection = window.getSelection();
let range = selection.getRangeAt(0);
let startContainer = range.startContainer;
let startOffset = range.startOffset;
let endContainer = range.endContainer;
let endOffset = range.endOffset;
// ......
let newRange = document.createRange();
newRange.setStart(startContainer, startOffset);
newRange.setEnd(endContainer, endOffset);
selection.removeAllRanges();
selection.addRange(newRange);
但是,有些操作可能会自动修改选区,所以要为恢复选区添加延迟:
setTimeout(function(){
selection.addRange(newRange);
}, 50);
三、 编辑 DOM,修改样式
如果段落中是一段即加粗又倾斜的文字等较复杂的样式,需要使用document.execCommand:
document.execCommand('bold'); // 加粗所选
document.execCommand('italic'); // 倾斜所选
document.execCommand('underline'); // 下划线所选
document.execCommand('createLink', true, 'https://indeex.club'); // 为所选文字加链接
document.execCommand('unlink'); // 取消链接
document.execCommand('formatBlock', true, 'h1');
document.execCommand('formatBlock', true, 'p');
浏览器还提供了copy、cut和paste等方法,这里不再赘述。
四、事件侦听
除了change或keyup事件,拖拽还要使用mouseup事件,但是都比较麻烦。所以要使用 Mutation Observer 机制,略。
五、兼容
然后就是不同浏览器的兼容问题了,ummmm…..
先这样吧。
code enjoy!😜😜😜
作者:indeex
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。