第一篇文章选择写「选区」,原因是编辑器的「编辑」实质是选择后修改,而其中的选择操作就是所要介绍的选区在技术层面的实现,可以说是最核心的功能。
本文会先介绍选区的基本概念,再引申介绍光标的实质,最后讲解如何利用选区来实现选择文本设置字号的需求。
选区介绍
选区在具体涉及两个不同的概念,包括了选择「Selection」和范围「Range」。
firefox多选区效果
上图的蓝色背景就是范围,所以范围别名也叫「拖蓝」。
控制选区本质上就是对范围的操作,因为范围提供了对用户选区的内容进行增删改的能力。选择是范围的集合,如上图所示一个选区可以包含多个范围。
选择提供了 「setBaseAndExtent」、「setPosition」等快捷修改范围的能力,简单场景(例如扩大/缩小用户选择区域)可直接使用选择进行操作。
小技巧:
选择 「toString」 不会包括隐藏元素,但范围会包括一切不可见元素,看个具体的例子。
对上述代码进行选中:
「Selection」的结果是“见可”,而「Range」的结果是“见不可见不可见可”,不可见元素内的文本信息也能被获取。
光标介绍
讲到选区就不得不提光标,光标其实也是一个范围(拖蓝),是起点和终点相同的特殊范围。
富文本编辑器很多功能其实都需要在光标处做操作,例如常见的插入一张图片,本质就是先通过获取范围,然后利用 「insertNode」 插入 标签。
小技巧:
编辑器中调整字体大小时光标的大小也需要随之调整。但如果在光标处仅仅插入24像素字体大小的 ,光标的高度并不会发生变化,如下图。
span24中计算出来的字号依然是15px
这时就要使用「零宽字符」(\ufeff)作为文本节点填充进标签。
24px字号光标比15px高
但要注意的是,编码中多一个「零宽字符」需要有很多额外的逻辑来保证它的位置正确并且及时被清理,否则在换行、退格时很容易发生格式无法继承的问题,后续会再写篇文章专门讲格式继承(选区合并)。
选择文本调整字号实战
最后我们来利用选区实现一个选择文本并调整字号大小的功能。
如果简单对上述结构的c至j文字调整字号,用以下代码即可实现:
但「execCommand」对字号只有1到7个档位,如果我们希望灵活控制字号大小,就需要精确控制选区内的每个结构。
我们可以利用范围提供的「insertNode」方法在光标的起始和终点插入特殊的标记(就像插入图片一样),插入后我们得到了如下的结构:
接下来就是利用 「nextSibling」 这个属性,从 start 处开始找相邻的文本节点,给文本节点添加字体的样式,直到找到 end 处终止。
寻找相邻节点
最后再把插入的标记节点删除即可完成选择文本调整字号的特性,最终的结构如下:
虽然实现了调整字号的功能,但最终的标签存在了一定程度的冗余,要做得更完善还需要合并结构以及还原拖蓝位置,这部分如何实现就留给读者思考了。
总结
选区是富文本编辑器的基础,包括了「Selection」和「Range」两个概念,并且我们知道了光标的实质也是范围。结尾的示例可以看到利用选区能对用户选中的格式做修改。
「Selection」和「Range」有很多属性、事件和方法,想真正理解它们的特性,最好的方法还是动手编码实践一下。这里推荐一篇文章,里面对每个api做了较详细的描述。
推荐文章:
https://zh.javascript.info/selection-range
领取专属 10元无门槛券
私享最新 技术干货