如何在不改变DOM的情况下计算文本选择的高度?

6
我正在使用Range来处理所选文本。我想计算从某人开始选择文本到他们结束的高度。 我尝试了一个span标签,放在选定范围的开头和结尾,然后可以准确地计算出高度,但它改变了DOM并阻止了我进行其他范围操作,比如突出显示先前选择的文本。 我还尝试收集mousedown和mouseup位置,但我需要从所选文本顶部到释放选择的文本底部的准确高度,并不总是这样。 所以我想知道是否有一种方法可以计算文本选择的高度而不更改DOM?
3个回答

6
这取决于您需要处理哪些浏览器。以下是一个函数,适用于IE >= 4和支持Range中的getClientRects()的浏览器(Firefox >= 4,自2009年以来的WebKit,Opera)。如果您需要支持早期的浏览器,则需要修改DOM,只要将DOM恢复到其先前状态即可,这实际上是可以的。
jsFiddle: http://jsfiddle.net/W84yW/ 代码:
function getSelectionHeight() {
    var selHeight = 0;
    if (document.selection && document.selection.type == "Text") {
        var textRange = document.selection.createRange();
        selHeight = textRange.boundingHeight;
    } else if (window.getSelection) {
        var sel = window.getSelection();
        if (sel.rangeCount > 0) {
            var range = sel.getRangeAt(0);
            if (!range.collapsed && range.getClientRects) {
                var startRange = range.cloneRange();
                startRange.collapse(true);
                var selTop = startRange.getClientRects()[0].top;
                startRange.detach();
                var endRange = range.cloneRange();
                endRange.collapse(false);
                selHeight = endRange.getClientRects()[0].bottom - selTop;
                endRange.detach();
            }
        }
    }
    return selHeight;
}

0
我会获取所选文本,并将其放置在一个具有相同宽度和样式的隐藏div中,然后获取其高度。

问题是如何在不更改DOM的情况下完成这个操作。一个隐藏的div正在改变DOM。 - jfriend00
如果要使用一个单独的文本副本来进行测量,我认为方法是将其放置在可见div中,但设置position: absolute和left: -10000px; 这告诉浏览器完全布局它,但它实际上永远不会显示或导致滚动条。 - jfriend00
@jfriend00 是的,但我想OP的意思是在文本块中“更改”DOM;此外,使用display: none不会显示任何滚动条,并适用于此情况。 - jackJoe
一些浏览器不会为display:none的元素设置高度。 - jfriend00
@jfriend00 哪些浏览器?我刚用这个测试了一下“旧”的浏览器:http://jsfiddle.net/jackJoe/Zxb5E/。它适用于IE7 + 8、Safari 4、FF 3、Opera 10,这些都是相当老的浏览器,它们理解隐藏高度,尽管不太好玩,但事实上隐藏时高度是不同的!(除了FF 3之外),我的测试获取高度,隐藏div,获取高度并添加两个段落,这就是缺少的高度,很奇怪。 - jackJoe

0

我认为隐藏DIV的方法不会起作用。许多浏览器要么没有高度,要么对于像那样隐藏的元素高度为0。

也许如果你克隆DOM的那一部分并将其添加到文档中,使用一些疯狂的位置(比如left:-1000px),你可以得到该值。

无论如何,如果范围对象不能为您提供此数据,则我认为您必须使用解决方法来获得一致的结果。


隐藏一个 div(无论是通过 visibility: hidden 还是 display: none),仍然可以通过 JavaScript“看到”,你可以试试,我已经试过了 :) - jackJoe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接