了解如何在单词包装元素中拆分行



假设你在网页中有类似<div>foo bar</div>的东西。这可能会呈现为

foo bar

foo
bar

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

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

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

如果块级元素仅包含纯文本,则可以使用两个范围的 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);
<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>

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

jsFiddle的演示。

我不确定是否有办法使用 DOM 执行此操作,但这是我的解决方案:

let divs = document.querySelectorAll('div');
for (let div of divs) {
let wordBreak = [];
const words = div.innerText.split(" ");
div.innerText = words[0];
let beforeBreak = words[0];
let height = div.offsetHeight;
for (let i = 1; i < words.length; i++) {
div.innerText += ' ' + words[i];
if (div.offsetHeight > height) {
height = div.offsetHeight;
wordBreak.push(beforeBreak);
beforeBreak = words[i];
} else {
beforeBreak += ' ' + words[i];
}
}

wordBreak.push(beforeBreak);
console.log(wordBreak);
}
<div style="width: 5%; overflow-wrap: break-word">foo bar</div>
<div style="overflow-wrap: break-word;">foo bar</div>
<div style="width: 50%; overflow-wrap: break-word">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin sit amet tellus et elit ultricies iaculis bibendum
eu arcu. Nam ut ante tellus, sed semper velit. Pellentesque ac odio ligula. Donec sem dui, iaculis vel euismod a,
vulputate ac mi. Nam ut lorem neque. Praesent lacinia molestie est, et luctus nunc venenatis id. Vivamus id mi elit.
Fusce in magna at diam commodo tincidunt at quis ante. Donec ac dolor risus. Quisque vehicula ultrices faucibus
</div>

注意:这个答案与此答案类似,但使用本机JS和您所描述的最终结果。

我正在寻找会返回类似 ["foo"、"bar"] 的 JavaScript 代码(在确实发生包装的情况下(。

我没有相同的解决方案,但我有一个与此非常相似的想法。 请参阅下面的代码片段并检查代码,然后减小屏幕尺寸并检查代码。 您将在站立下

它将帮助您根据设备宽度获取线条。{ span class="line-0", span class="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());
});
#example {
l1ine-height: 200%;
font-size: 2em;
text-transform: uppercase;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p id=example>Foo Bar</p>

最新更新