背景
PDF划词拾取在许多业务场景中都有使用,典型的场景例如划词翻译、划词批注、下划线、删除线等等。网上通用做法是用css实现下划线、删除线、高亮。但是这种做法通常不利于持久化保存、还原、同时也无法将批注保存到pdf文件中;因此如果希望拾取的文字或批注能持久地保存到独立文件或PDF中,则需要通过svg来绘制;当然也可以使用canvas画布来绘制。
实现划词拾取的困难点
- 通过selection拾取到的文字通常是一个标签中的一部分;
- 即使对标签进行切割也会破坏dom结构,导致二次拾取出错;
- 在跨行拾取时如何判定相邻div;
解决方案
在前端js提供的选择函数中(js selection)只会提供一个anchor node和一个focus Node 分别表示起始的div节点和终止的div节点。#text类型的节点可以根据起始的索引进行切割。anchor Node可以进行字符串切割,将切割到的字符串放进新的div、并计算div的clientBoundBox,从而得到宽高以及选择的起始位置;
分别对起始和终止的节点进行切割后就可以得到首行选中的内容的位置信息以及尾行的选中内容的位置信息;
然后再将起始和终止节点中间和盒子进行合并、保证一行只有一个矩形box,最后将这些矩形盒子分别绘制出来即可;如果需要保存也可以保存矩形盒子的信息。如果需要考虑缩放可以将矩形盒子的坐标转换成相对页面宽高的百分比坐标,这样随页面缩放可以自动缩放;
在对文字切割以后形成的新的节点破坏了dom树、需要将插入的节点删除、重新还原dom树、否则文字无法二次选中;
在跨行拾取时,当页面文字布局情况比较特殊时,可能会涉及一些策略问题,需要针对特殊清康特殊处理;同时还有反向拾取,目前还未研究,后续补充。