Получить каждую строку выделения текста - PullRequest
1 голос
/ 10 апреля 2019

У меня есть текстовый блок с фиксированной шириной, и я пытаюсь получить каждую строку текста boundingClientRect.Мне интересно, есть ли у Selection api метод для этого, что я просто скучаю.Есть ли какой-нибудь простой способ получить каждую строку выделенного текста?

В настоящее время единственное решение, которое я могу придумать, - это создать интервалы вокруг каждого символа в выделении, а затем объединить символы, если они имеют одинаковый yкоординаты в их ограничивающем прямоугольнике клиента.Это очень неэффективно, поэтому мне любопытно, есть ли более простой метод.

Ниже приведено графическое представление того, что я пытаюсь найти.API выбора дает только прямоугольник вокруг поля в целом, включая невыбранный текст.Я пытаюсь найти прямоугольники вокруг каждой строки выделения.

What the selectino api bounding box gives you and what I'm trying to find

Выбор будет всегда быть текстом.Поэтому не нужно беспокоиться об изображениях.Однако они могут находиться в разных элементах, но они будут иметь одинаковый тип тега (например, без ссылок или тегов em / strong).

Возвращает выбранный блок текста

const selection = window.getSelection().getRangeAt(0);

markjs имеет решение для выделения, которое оборачивает все в один тег.

<mark><p>hello there</p></mark>

Мой план состоял в том, чтобы использовать подобный алгоритм, чтобы получить внутренний html и пройти через каждый символ и обернуть его в новый тег с именем класса, который затем может быть найден, а затем вычислен ограничивающий прямоугольник.Это просто написать, но кажется, что вычислительно тяжелее, чем хотелось бы.

Есть ли способ просто получить ограничивающий прямоугольник каждой строки?

1 Ответ

2 голосов
/ 10 апреля 2019

Вы можете использовать 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.
...