У меня есть текстовый блок фиксированной ширины, и я пытаюсь получить каждую строку текста boundingClientRect. Мне интересно, есть ли у Выбор API метод для этого, который я просто пропустил. Есть ли простой способ получить каждую строку выделенного текста?
В настоящее время единственное решение, которое я могу придумать, - это создать диапазоны вокруг каждого символа в выборе, а затем объединить символы, если они имеют одинаковую координату y в их ограничивающем клиентском прямоугольнике. Это очень неэффективно, поэтому мне любопытно, есть ли более простой метод.
Ниже представлено изображение того, что я пытаюсь найти. API выбора дает только прямоугольник вокруг поля в целом, включая невыделенный текст. Я пытаюсь найти прямоугольники вокруг каждой линии выбора.
Выбор будет всегда текстовым. Так что не нужно беспокоиться об изображениях. Однако они могут быть в разных элементах, но они будут одного типа тегов (например, без ссылок или тегов em/strong).
Возвращает выделенный блок текста
const selection = window.getSelection().getRangeAt(0);
В МаркДжс есть решение для выделения, заключающее все в один тег.
<mark><p>hello there</p></mark>
Мой план состоял в том, чтобы использовать аналогичный алгоритм, чтобы получить внутренний html и пройтись по каждому символу и обернуть его новым тегом с именем класса, который затем можно было бы найти, а затем вычислить ограничивающую рамку. Это просто написать, но кажется более сложным в вычислительном отношении, чем мне бы хотелось.
Есть ли способ просто получить ограничивающую рамку каждой строки?
Вместо этого вы можете использовать getClientRects
:
var selectionDivs = [];
document.addEventListener('selectionchange', function () {
var range = window.getSelection().getRangeAt(0);
var rects = range.getClientRects();
selectionDivs.forEach(function (div) {
div.remove();
});
selectionDivs = [];
for (var i = 0; i < rects.length; i++) {
var div = document.createElement('div');
div.className = 'rect';
div.style.left = (window.scrollX + rects[i].left) + 'px';
div.style.top = (window.scrollY + rects[i].top) + 'px';
div.style.width = rects[i].width + 'px';
div.style.height = rects[i].height + 'px';
document.body.appendChild(div);
selectionDivs.push(div);
}
});
.rect {
position: absolute;
pointer-events: none;
border: 1px solid black;
}
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Nunc sed velit dignissim sodales ut eu. Imperdiet sed euismod nisi porta lorem mollis. Nisl suscipit adipiscing bibendum est. Elit eget gravida cum sociis natoque penatibus et. Mauris in aliquam sem fringilla. In arcu cursus euismod quis viverra. Imperdiet sed euismod nisi porta lorem mollis. Eget gravida cum sociis natoque penatibus et. Sed libero enim sed faucibus turpis in eu mi bibendum. Varius duis at consectetur lorem donec massa. Facilisi nullam vehicula ipsum a arcu. Libero justo laoreet sit amet cursus sit. At in tellus integer feugiat scelerisque varius morbi. Est ullamcorper eget nulla facilisi etiam. Semper eget duis at tellus at urna condimentum mattis.
Рад, что это полезно!
Это работает! Я очень надеялся, что есть простое решение этой проблемы. Рад видеть, что есть. Спасибо за помощь.