0x0. 效果
先上效果图:
0x1. 起因
得到 APP 中有个文稿模块, 这部分是内嵌的前端开发的 web 页面, 支持在客户端和微信中访问, 其中有一个称为划线笔记的功能, 就是长按文字之后, 对选中的文字做标记, 这是背景.
在一次需求迭代过程中, 产品对划线笔记的功能提出了一些问题, 比如为什么 iOS 和 Android 的样式不统一 (用的是系统原生的长按选中), 是不是可以实现单击就可以选中文字, 是不是可以自定义样式, 是不是可以正反选......
听到这里我的内心是这样的
本着跟产品友好相处的原则, 我当即表示这个些需求很棒, 我需要认真想一下怎么拒绝.
0x2. 分析
当然, 想法归想法, 做还是要想办法做的
从产品的需求看, 只有自己模拟一个系统的长按选中才可以满足产品现阶段及将来可能潜在的需求. 如果模拟一个长按选中, 大概需要解决这么几个问题:
需要禁用系统的长按选择文字
需要获取到点击字符的确切位置
需要能够模拟选中时的矩形背景
0x3. 实现
针对刚才的分析, 大概可以这样实现:
第一点, 添加 user-select: none 的样式, 这样可以直接禁用系统的文字选择; 第二点, 能够间接或者直接获取字符位置的 dom API, 大概只有间接的通过
Range.getClientRects()
第三点, 最初构思有两个方案, 一个是直接在文字中插入标签, 这样势必会改变整个 dom 的结构, 对后续的标记造成影响, 于是采用第二个方案, 直接加一个 svg 层, 通过 svg 的多边形和矩形来绘制
最后, 具体实现见 https://github.com/luojilab/easy-marker , 我们已经把这个方案开源出来了
这个方案有以下有点:
自定义选择样式
点击选中当前句子
长按选中当前句子
正向反向选择
高亮标记选中的文字
......
有需要的小伙伴欢迎 star, iusse, pr 走起.
来源: https://juejin.im/post/5b07abb451882538be0d24ce