Получение выбранной позиции текста - PullRequest
34 голосов
/ 03 марта 2011

В настоящее время я получаю выделенный текст в браузере следующим образом:

window.getSelection();

Теперь мне нужно показывать всплывающую подсказку над этим текстом при нажатии настраиваемой клавиши (обратите внимание, что мышь больше не может находиться над текстом), поэтому для этого мне нужна абсолютная позиция выбранного текста.

Есть ли способ сделать это, возможно, обернуть этот текст внутри тега и затем получить смещения? Он просто должен работать в Chrome, а не во всех браузерах.

Ответы [ 3 ]

50 голосов
/ 26 июля 2013
s = window.getSelection();

Возвращает выбор.Поэтому попробуйте

s = window.getSelection();
oRange = s.getRangeAt(0); //get the text range
oRect = oRange.getBoundingClientRect();

oRect будет ограничительным прямоугольником в клиентских (фиксированных) координатах.

15 голосов
/ 06 марта 2011

Самый простой способ - вставить временный элемент маркера в начало или конец выделения и получить его позицию. Ранее я продемонстрировал, как это сделать, при переполнении стека: Как разместить элемент рядом с выделенным текстом пользователя?

0 голосов
/ 24 апреля 2017

Перед использованием getBoundingClientRect необходимо знать эту заметку :

Рабочий проект CSSOM указывает, что он возвращает ClientRect для каждого поля границы

И под этим «стандартом»:

Для встроенного элемента два определения одинаковы. Но для блочного элемента Mozilla вернет только один прямоугольник.

Поэтому, если кто-то, читающий этот пост, хочет найти общее решение для более точных позиций и макетов выбранных текстов, я предлагаю следующие подходы:

Вариант 1: Найти точную начальную и конечную точку текста с помощью , вставив невидимые элементы . Затем вычислите выбранные прямоугольники линии с извлеченной вычисленной высотой линии и шириной контейнера. Используемые API: window.getComputedStyle .

  • Pro: результат будет наиболее точным для каждой строки текста.
  • Con: 1) Если выделение происходит между несколькими узлами с разной высотой и шириной линии, алгоритм становится сложным. 2) И вам необходимо реализовать алгоритм вычислений, который занимает слишком много времени при реализации простой функции.

Вариант 2: Оберните каждый текст тщательно разработанным внутренним элементом, извлекая расположение каждого блока и объединение результатов в строки.

  • Pro: работает для всех непрерывных выборов (это в основном означает все случаи в текущих реализациях основного браузера). Достаточно хорошая точность для каждой строки текста.
  • Con: 1) В некоторых случаях его результат немного неточен, так как добавляет ширину ошибки kerning . 2) Это медленно на очень большой выбор текстов.

Для варианта 2 rangeblock - это существующая реализация с простым API, который дает вам абсолютный макет каждой строки текста:

let block = rangeblock.extractSelectedBlock(window, document);
console.info("Text layout: " + JSON.stringify(block.dimensions));
// output: Text layout: {Left: 100, Top: 90, Width: 200, Height: 50}
...