Координаты выделенного текста на странице браузера
Мне нужны координаты в пикселях начала выделения текста (в любом месте страницы, а не в текстовой области).
Я попытался использовать координаты курсора, но это не сработало, потому что координаты курсора и начало выделения не всегда совпадают (например, когда пользователь перетаскивает текст).
Я надеюсь, что у кого-то есть решение!
3 ответа
В браузерах IE >= 9 и не IE (Firefox 4+, браузеры WebKit, выпущенные с начала 2009 г., Opera 11, возможно, ранее) вы можете использовать getClientRects()
метод Range
, В IE 4 - 10 вы можете использовать boundingLeft
а также boundingTop
свойства 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, и теперь она исправлена.
Приведенный выше ответ от TimDown не работает, если каретка находится в пустом элементе.
Код ниже решает проблему. Обратите внимание, что оно почти идентично решению TimDown, за исключением того, что этот код проверяет range.getClientRects()
массив имеет length>0
перед звонком range.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 };
}
Приведенный ниже код представляет собой упрощенную и модернизированную версию решения, предоставленного Тимом Дауном. Он также использует более совместимый с браузером 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 };
}