查找如何在自动换行元素中分割行

saf*_*f32 5 html javascript css dom

假设您有类似<div>foo bar</div>网页的内容。这可能会呈现为

foo bar
Run Code Online (Sandbox Code Playgroud)

或者

foo
bar
Run Code Online (Sandbox Code Playgroud)

取决于元素是否自动换行(这取决于其宽度和各种 css 属性的值,例如white-spaceword-breakoverflow-wrap等)。

有没有办法确定浏览器如何在自动换行方面呈现此类元素中的文本?即,我正在寻找会返回类似内容的javascript代码["foo", "bar"](在确实发生换行的情况下)。

似乎getClientRects为每行返回单独的框(它似乎仅适用于内联元素)。但我正在寻找一些也提供有关文本信息的东西。

Tee*_*emu 5

如果块级元素仅包含纯文本,则可以使用两个范围的 DOMRect 对象获取自动换行的文本。在元素内创建一个文本节点的范围 ( range) 以获取一行文本,并hTracker在增加范围的结束位置时创建另一个范围 ( ) 来记录 DOMRect 对象的高度。当范围的高度发生变化时,将前一行的文本存储range到一个数组中,并将起始位置设置range为当前行的行尾。代码如下:

function showLines(e) {
  const el = e.target,
    node = el.firstChild,
    range = document.createRange(),
    len = e.target.textContent.length,
    texts = [];
  let hTracker, y, oldY;
  range.selectNodeContents(el);
  range.collapse();
  hTracker = range.cloneRange();
  hTracker.setEnd(node, 1);
  oldY = hTracker.getBoundingClientRect().height;
  for (let n = 0; n < len; n++) {
    hTracker.setEnd(node, n);
    range.setEnd(node, n);
    y = hTracker.getBoundingClientRect().height;
    if (y > oldY || n === len - 1) {
      // Line changed, resume the previous range (not when at the end of the text)
      range.setEnd(node, n - (n !== len - 1));
      // Store the text of the line
      texts.push(range.toString());
      // Set the start of the range to the end of the previous line
      range.setStart(node, n - 1);
      oldY = y;
    }
  }
  console.log(texts);
};

document.addEventListener('click', showLines);
Run Code Online (Sandbox Code Playgroud)
<div>
  depending on whether the element gets word wrapped (which depends on its width and the value of various css properties such as white-space, word-break, overflow-wrap, etc). Is there a way to determine how has the browser rendered the text in such an element
  with respect to word wrapping? i.e., I am looking for javascript code that would return something like ["foo", "bar"] (in the case wrapping did occur). It seems that getClientRects returns separate boxes for each line (it appears to be working for inline
  elements only). But I am looking something that also gives information about the text.
</div>
Run Code Online (Sandbox Code Playgroud)

Range.getBoundingClientRect还不是标准方法,但它得到了广泛支持。这也可以用单个范围来完成,但这样这个想法可能更容易理解。

jsFiddle 上的演示可以玩。


Anm*_*eja 0

我正在寻找会返回类似 ["foo", "bar"] 之类的 JavaScript 代码(在确实发生换行的情况下)。

我没有相同的解决方案,但我有一个与此非常相似的想法。请参阅下面的代码片段并检查代码,然后缩小屏幕尺寸并再次检查代码。你会明白的

它将帮助您根据设备宽度获取线条。{ 跨度类=“line-0”,跨度类=“line-1” }

var words = $('#example').text().replace(/\t/g, ' ').replace(/\r/g, ' ').replace(/\n/g, ' ').replace(/\s+/g, ' ').split(' ');
//console.log(words);
$('#example').html('<span>' + words.join('</span> <span>') + '</span>');
var lines = [];
$('#example span').each(

  function(i, e) {
    var offsettop = $(e).offset();
    if (lines.indexOf(offsettop.top) === -1) {
      lines.push(offsettop.top);

    }
    $(e).addClass('line' + lines.indexOf(offsettop.top));
  });

var line = [];
$('#example span.line1').css('background', 'red').each(function(i, e) {
  line.push($(e).html());
});
Run Code Online (Sandbox Code Playgroud)
#example {
  l1ine-height: 200%;
  font-size: 2em;
  text-transform: uppercase;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p id=example>Foo Bar</p>
Run Code Online (Sandbox Code Playgroud)