浏览器页面中选定文本的坐标

Coordinates of selected text in browser page

本文关键字:文本 坐标 浏览器      更新时间:2023-09-26

我需要以像素为单位的文本选择开始的坐标(在页面上的任何位置,而不是在文本区域中)

我尝试使用光标坐标,但这不是很好地工作,因为光标坐标和选择的开始并不总是相同的(例如当用户拖动文本时)。

我希望有人有解决办法!

在IE>= 9和非IE浏览器(Firefox 4+, 2009年初以来发布的WebKit浏览器,Opera 11,可能更早)中,您可以使用RangegetClientRects()方法。在IE 4 - 10中,您可以使用TextRangeboundingLeftboundingTop属性,这些属性可以从选择中提取出来。这里有一个函数,可以在最新的浏览器中做你想做的事情。

请注意,在某些情况下,你可能会错误地得到坐标0, 0,正如@Louis在评论中提到的。在这种情况下,您将不得不退回到临时插入元素并获取其位置的解决方案。

jsFiddle: http://jsfiddle.net/NFJ9r/132/

代码:

function getSelectionCoords(win) {
    win = win || window;
    var doc = win.document;
    var sel = doc.selection, range, rects, rect;
    var x = 0, y = 0;
    if (sel) {
        if (sel.type != "Control") {
            range = sel.createRange();
            range.collapse(true);
            x = range.boundingLeft;
            y = range.boundingTop;
        }
    } else if (win.getSelection) {
        sel = win.getSelection();
        if (sel.rangeCount) {
            range = sel.getRangeAt(0).cloneRange();
            if (range.getClientRects) {
                range.collapse(true);
                rects = range.getClientRects();
                if (rects.length > 0) {
                    rect = rects[0];
                }
                x = rect.left;
                y = rect.top;
            }
            // Fall back to inserting a temporary element
            if (x == 0 && y == 0) {
                var span = doc.createElement("span");
                if (span.getClientRects) {
                    // Ensure span has dimensions and position by
                    // adding a zero-width space character
                    span.appendChild( doc.createTextNode("'u200b") );
                    range.insertNode(span);
                    rect = span.getClientRects()[0];
                    x = rect.left;
                    y = rect.top;
                    var spanParent = span.parentNode;
                    spanParent.removeChild(span);
                    // Glue any broken text nodes back together
                    spanParent.normalize();
                }
            }
        }
    }
    return { x: x, y: y };
}

由于这些评论,我提交了一个WebKit bug,现在已经修复了。

https://bugs.webkit.org/show_bug.cgi?id=65324

如果插入符号在空元素中,则TimDown的上述答案不起作用。

下面的代码解决了这个问题。请注意,除了在调用range.getClientRects()[0]

之前检查range.getClientRects()数组是否有length>0之外,它与TimDown的解决方案几乎相同。
function getSelectionCoords() {
    var sel = document.selection, range, rect;
    var x = 0, y = 0;
    if (sel) {
        if (sel.type != "Control") {
            range = sel.createRange();
            range.collapse(true);
            x = range.boundingLeft;
            y = range.boundingTop;
        }
    } else if (window.getSelection) {
        sel = window.getSelection();
        if (sel.rangeCount) {
            range = sel.getRangeAt(0).cloneRange();
            if (range.getClientRects) {
                range.collapse(true);
                if (range.getClientRects().length>0){
                    rect = range.getClientRects()[0];
                    x = rect.left;
                    y = rect.top;
                }
            }
            // Fall back to inserting a temporary element
            if (x == 0 && y == 0) {
                var span = document.createElement("span");
                if (span.getClientRects) {
                    // Ensure span has dimensions and position by
                    // adding a zero-width space character
                    span.appendChild( document.createTextNode("'u200b") );
                    range.insertNode(span);
                    rect = span.getClientRects()[0];
                    x = rect.left;
                    y = rect.top;
                    var spanParent = span.parentNode;
                    spanParent.removeChild(span);
                    // Glue any broken text nodes back together
                    spanParent.normalize();
                }
            }
        }
    }
    return { x: x, y: y };
}

下面的代码是Tim Down给出的解决方案的简化和现代化版本。它还使用了一个更兼容浏览器的选择API (window.getSelection()而不是window.document.selection)

type Coord = {
  x: number;
  y: number;
};
// atStart: if true, returns coord of the beginning of the selection,
//          if false, returns coord of the end of the selection
function getSelectionCoords(atStart: boolean): Coord | null {
  const sel = window.getSelection();
  // check if selection exists
  if (!sel.rangeCount) return null;
  // get range
  let range = sel.getRangeAt(0).cloneRange();
  if (!range.getClientRects) return null;
  // get client rect
  range.collapse(atStart);
  let rects = range.getClientRects();
  if (rects.length <= 0) return null;
  // return coord
  let rect = rects[0];
  return { x: rect.x, y: rect.y };
}