没人回答我.. 自己回答了..
操作 contenteditable 的区域应该当作 HTML 上选择高亮内容来处理了.
旧的 API 接触不多, 新的 API 主要是 Selection 跟 Range 两个 API,
Selection 对应的是界面上的选中内容, 而 Range 是 Selection 当中的一个选中的区域.
简单的理解是, 一个 Selection 里会有多个 Range, Range 包含起始位置结束位置等等,
起始未知需要知道在哪个节点, 偏移量是多少等等
当然还有根据 Selection 跟 Range 用上面的位置信息来操作的 API
具体操作的代码大概要结合 StackOverflow 上具体的用例来理解的了
简单的自己写一个比如, 选中点击位置...
jssel = getSelection()
document.onclick = function(event) {
event.preventDefault();
range = new Range;
range.selectNode(event.target);
sel.removeAllRanges();
sel.addRange(range)
}
这个两个 API 的兼容性有一些问题, 比如 new Range 会在 Safari 保存,
比如 range.baseNode 在 Firefox 下不存在..
为了减少兼容性造成的影响, 可以用 rangy 这个模块:
/timdown/rangy/wiki
有点答跑题了.. 后面回到重点.. 答案在 MDN 关于这两个 API 的文档当中,
在 Range 的示例当中, 有试验的新 API 来提供对应的功能
Range.getBoundingClientRect()
Returns a ClientRect object which bounds the entire contents of the Range; this would be the union of all the rectangles returned by range.getClientRects().
Range.getClientRects()
Returns a list of ClientRect objects that aggregates the results of Element.getClientRects() for all the elements in the Range.
这两个 API 就可以返回选中的 range 的像素位置了
然后按照文档的提示, 对于元素还有 getClientRects 这个 API 可以用于获取标签的像素位置:
The Element.getClientRects() method returns a collection of rectangles that indicate the bounding rectangles for each box in a client.
写个脚本测试一下, 确实 OK:
jsdocument.onclick = function(event) {
event.preventDefault()
console.log(event.target.getClientRects()[0])
}
最近想到了一个新的方案, 因为获取选区是有 API 的, 我就模拟一个选区
就是说从光标开始往前或者往后选中一个字符, 然后获取选取的位置,
获取像素位置用到 getBoundingClientRect 这个 API, 完整代码如下:
/jiyinyiyong/f79c2bdf3fa646042173
不过有些细节还是没解决, 比如, 没有字怎么办? 选中一个字如果跨行了呢?
一般的情况, 我希望能够借助这个 API 完成.