获取文本选择的每一行

Get each line of a text selection

我有一个固定宽度的文本块,我正在尝试获取每一行文本的 boundingClientRect。我想知道 Selection api 是否有这样做的方法,我只是想念它。有什么简单的方法可以获取所选文本的每一行?

目前,我能想到的唯一解决方案是围绕选择中的每个字符创建跨度,然后如果字符在其边界客户端矩形中具有相同的 y 坐标,则加入这些字符。这样效率很低,所以我很好奇有没有更简单的方法。

下面是我要查找的内容的图像表示。选区api只给出了整个方框周围的矩形,包括未选的文字。我试图在每条选择线周围找到矩形。

所选内容始终为文本。因此无需担心图像。然而,它们可能在不同的元素中,但它们将是相同的标签类型(例如没有链接或 em/strong 标签)。

Returns 选定的文本块

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

markjs 有一个突出显示的解决方案,将所有内容包装在一个标签中。

<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.