文本区域 - 如何计算换行的行数/行数

5

我需要一些函数,可以计算行数(我知道在stackoverflow上有超过几百个这样的问题),但在我的情况下,即使没有换行符(意思是“/n”),我也需要计算它们的数量,因为典型的函数只适用于有换行符的情况。

textarea.value.substr(0, textarea.selectionStart).split("\n").length;.

这意味着如果用户超出了行的最大长度,但没有使用"enter"键,文本会在"新行"上显示。我不知道该如何更好地描述它,所以这里有一个例子:fiddle https://jsfiddle.net/fNPvf/12872/。试着写一个没有空格、换行等的长句子,你就会看到问题所在。
我真正不想要的是 CSS 规则 nowrap、overflow-x 等。

也许可以尝试这个 https://dev59.com/dHI-5IYBdhLWcg3wn525#1761203 - Erick Souza
哇,我之前已经尝试过这个,但它没有正常工作。不过如果我稍微编辑一下,很可能就能行了。 - Kuba Šimonovský
2个回答

14

给你。

/** @type {HTMLTextAreaElement} */
var _buffer;

/**
* Returns the number of lines in a textarea, including wrapped lines.
*
* __NOTE__:
* [textarea] should have an integer line height to avoid rounding errors.
*/
function countLines(textarea) {
    if (_buffer == null) {
        _buffer = document.createElement('textarea');
        _buffer.style.border = 'none';
        _buffer.style.height = '0';
        _buffer.style.overflow = 'hidden';
        _buffer.style.padding = '0';
        _buffer.style.position = 'absolute';
        _buffer.style.left = '0';
        _buffer.style.top = '0';
        _buffer.style.zIndex = '-1';
        document.body.appendChild(_buffer);
    }

    var cs = window.getComputedStyle(textarea);
    var pl = parseInt(cs.paddingLeft);
    var pr = parseInt(cs.paddingRight);
    var lh = parseInt(cs.lineHeight);

    // [cs.lineHeight] may return 'normal', which means line height = font size.
    if (isNaN(lh)) lh = parseInt(cs.fontSize);

    // Copy content width.
    _buffer.style.width = (textarea.clientWidth - pl - pr) + 'px';

    // Copy text properties.
    _buffer.style.font = cs.font;
    _buffer.style.letterSpacing = cs.letterSpacing;
    _buffer.style.whiteSpace = cs.whiteSpace;
    _buffer.style.wordBreak = cs.wordBreak;
    _buffer.style.wordSpacing = cs.wordSpacing;
    _buffer.style.wordWrap = cs.wordWrap;

    // Copy value.
    _buffer.value = textarea.value;

    var result = Math.floor(_buffer.scrollHeight / lh);
    if (result == 0) result = 1;
    return result;
}

此处演示


1
好的,这看起来非常有前途。不幸的是,这个话题已经两年了。我不再在这个项目上工作:D。无论如何,感谢你在这里花费的时间,希望点赞能让你满意。也许对于未来的某个人来说,这个答案会很有用。 - Kuba Šimonovský
2
我正在使用Dart版本的此函数来创建一个自定义文本区域(类似于paper-textarea),它可以根据其值自动增长/缩小。为了启用该功能,我进行了大量搜索以计算文本区域中行数的方法,但找不到一个好的答案。然后,我想出了这个函数并在这里分享,以便其他人可以使用。 - Kin
哎呀!我花了将近4个小时来调整画布和DOM元素,以创建文本元素,计算宽度并将其除以textArea的宽度。就像这个答案一样。但由于某种原因,我的解决方案并不适用于所有字符!我没有尝试调整高度和行高!这个方法甚至可以完美地处理表情符号、大型UTF-8字符和所有这些东西! - 15 Volts
哎呀!我花了将近4个小时来调整画布和DOM元素,以创建文本元素,计算宽度并将其除以文本区域的宽度。就像这个答案一样。但是由于某种原因,我的解决方案对于所有字符都不起作用!我没有尝试调整高度和行高!这个方法甚至可以完美地处理表情符号、大型UTF-8字符和其他所有东西! - undefined

0

如果我理解问题正确的话,您需要计算两件事情。

  1. "\n"硬换行符的数量。
  2. 超过X个字符的行数。

这里是一些伪代码:

var lineLengthLimit = 40;
var lineCounter = 0;

foreach(lines as line){
    lineCounter+=Math.floor(line.length/lineLengthLimit);
}

lineCounter += lines.length;

另一个选择可能是这个人建议的:https://dev59.com/K3A65IYBdhLWcg3wqQg8#3697249,但它似乎有点可疑。


你认为在自动换行中没有“不可见”的字符(例如/n新行)吗? - Kuba Šimonovský
2
你假设没有一行会换行超过一次吗? - stark
这是一个很好的观点。应该使用类似于“Math.floor(line.length/lineLengthLimit)”而不是“>”。让我考虑一下,然后我会更新我的答案。 - Matt
@stark 我不明白你的意思(我的英语不是很好,对此感到抱歉) - Kuba Šimonovský

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接