36

テキスト選択の先頭のピクセル単位の座標が必要です(テキストエリアではなく、ページ上の任意の場所)。

カーソル座標を使用してみましたが、カーソル座標と選択範囲の先頭が常に同じであるとは限らないため(たとえば、ユーザーがテキスト上をドラッグした場合)、これはうまく機能しませんでした。

私は誰かが解決策を持っていることを願っています!

4

3 に答える 3

67

IE> = 9および非IEブラウザー(Firefox 4以降、2009年初頭以降にリリースされたWebKitブラウザー、Opera 11、おそらくそれ以前)では、のgetClientRects()方法を使用できますRange。IE 4-10では、選択範囲から抽出できるのプロパティboundingLeftboundingTopプロパティを使用できます。TextRangeこれが最近のブラウザでやりたいことをする関数です。

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のバグを送信しましたが、修正されました。

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

于 2011-07-27T15:48:26.773 に答える
24

キャレットが空の要素にある場合、TimDownによる上記の回答は機能しません。

以下のコードは問題を解決します。このコードが呼び出す前にrange.getClientRects()配列が持っていることをチェックすることを除いて、TimDownのソリューションとほとんど同じであることに注意してくださいlength>0range.getClientRects()[0]

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 };
}
于 2014-10-21T19:56:46.157 に答える
3

以下のコードは、TimDownによって提供されたソリューションの簡略化された最新バージョンです。また、(の代わりに)よりブラウザ互換性のある選択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 };
}
于 2021-03-13T20:33:16.463 に答える