Answers:
如果div的大小取决于内容(我假设您的描述是这种情况),则可以使用以下方法检索div的高度:
var divHeight = document.getElementById('content').offsetHeight;
并除以字体行高:
document.getElementById('content').style.lineHeight;
或者,如果尚未显式设置行高,请执行以下操作:
var element = document.getElementById('content');
document.defaultView.getComputedStyle(element, null).getPropertyValue("lineHeight");
您还需要考虑填充和行间距。
编辑
完全独立的测试,显式设置行高:
function countLines() {
var el = document.getElementById('content');
var divHeight = el.offsetHeight
var lineHeight = parseInt(el.style.lineHeight);
var lines = divHeight / lineHeight;
alert("Lines: " + lines);
}
<body onload="countLines();">
<div id="content" style="width: 80px; line-height: 20px">
hello how are you? hello how are you? hello how are you? hello how are you?
</div>
</body>
line-height
(未明确设置)的更好方法是使用window.getComputedStyle(element, null).getPropertyValue('line-height')
一种解决方案是使用脚本将每个单词括在span标签中。然后,如果给定的span标签的Y尺寸小于其前一个标签的Y尺寸,则发生换行。
检出getClientRects()函数,该函数可用于计算元素中的行数。这是一个如何使用它的例子。
var message_lines = $("#message_container")[0].getClientRects();
它返回一个javascript DOM对象。通过执行以下操作可以知道行数:
var amount_of_lines = message_lines.length;
它可以返回每行的高度,甚至更多。将其添加到脚本中,然后查看控制台日志,以查看其可以完成的所有操作。
console.log("");
console.log("message_lines");
console.log(".............................................");
console.dir(message_lines);
console.log("");
尽管需要注意的几件事是,它仅在containing元素为内联时才有效,但是您可以使用block元素将containing inline元素包围起来,以控制宽度,如下所示:
<div style="width:300px;" id="block_message_container">
<div style="display:inline;" id="message_container">
..Text of the post..
</div>
</div>
尽管我不建议对这种样式进行硬编码。这只是出于示例目的。
我不满意这里和其他问题的答案。最高评分的答案没有考虑padding
或border
考虑,因此显然也忽略box-sizing
了。我的答案在这里和其他线程上结合了一些技术,以获得可以令我满意的解决方案。
这不是完美的:当无法为line-height
(例如normal
或inherit
)获取数值时,它仅使用font-size
乘以1.2
。在这种情况下,也许其他人可以建议一种可靠的方法来检测像素值。
除此之外,它还能够正确处理我抛出的大多数样式和案例。
jsFiddle用于测试和测试。也在下面内联。
function countLines(target) {
var style = window.getComputedStyle(target, null);
var height = parseInt(style.getPropertyValue("height"));
var font_size = parseInt(style.getPropertyValue("font-size"));
var line_height = parseInt(style.getPropertyValue("line-height"));
var box_sizing = style.getPropertyValue("box-sizing");
if(isNaN(line_height)) line_height = font_size * 1.2;
if(box_sizing=='border-box')
{
var padding_top = parseInt(style.getPropertyValue("padding-top"));
var padding_bottom = parseInt(style.getPropertyValue("padding-bottom"));
var border_top = parseInt(style.getPropertyValue("border-top-width"));
var border_bottom = parseInt(style.getPropertyValue("border-bottom-width"));
height = height - padding_top - padding_bottom - border_top - border_bottom
}
var lines = Math.ceil(height / line_height);
alert("Lines: " + lines);
return lines;
}
countLines(document.getElementById("foo"));
div
{
padding:100px 0 10% 0;
background: pink;
box-sizing: border-box;
border:30px solid red;
}
<div id="foo">
x<br>
x<br>
x<br>
x<br>
</div>
克隆容器对象并写2个字母并计算高度。这将返回应用了所有样式的实际高度,线条高度等。现在,计算高度对象/一个字母的大小。在Jquery中,高度优于填充,边距和边框,因此计算每行的实际高度非常好:
other = obj.clone();
other.html('a<br>b').hide().appendTo('body');
size = other.height() / 2;
other.remove();
lines = obj.height() / size;
如果您使用每个字母的高度不同的稀有字体,则此方法无效。但可用于所有普通字体,例如Arial,mono,Comic,Verdana等。使用字体进行测试。
例:
<div id="content" style="width: 100px">hello how are you? hello how are you? hello how are you?</div>
<script type="text/javascript">
$(document).ready(function(){
calculate = function(obj){
other = obj.clone();
other.html('a<br>b').hide().appendTo('body');
size = other.height() / 2;
other.remove();
return obj.height() / size;
}
n = calculate($('#content'));
alert(n + ' lines');
});
</script>
结果: 6 Lines
可以在所有浏览器中运行,而没有超出标准的罕见功能。
clone
→ cloneNode
,hide
→ style.visibility = "hidden"
,html('a<br>b')
→ textContent='a\r\nb'
,appendTo('body')
→ document.documentElement.appendChild
,height()
→getBoundingClientRect().height
对于那些使用jQuery的人http://jsfiddle.net/EppA2/3/
function getRows(selector) {
var height = $(selector).height();
var line_height = $(selector).css('line-height');
line_height = parseFloat(line_height)
var rows = height / line_height;
return Math.round(rows);
}
$(selector).css('line-height');
,您不会从该函数中得到一个数字。
我坚信现在不可能了。是的,但是。
IE7的getClientRects实现完全符合我的要求。在IE8中打开此页面,尝试刷新它以改变窗口宽度,并查看第一个元素中的行数如何相应变化。这是该页面上javascript的关键行:
var rects = elementList[i].getClientRects();
var p = document.createElement('p');
p.appendChild(document.createTextNode('\'' + elementList[i].tagName + '\' element has ' + rects.length + ' line(s).'));
对我来说不幸的是,Firefox总是为每个元素返回一个客户端矩形,而IE8现在也是如此。(Martin Honnen的页面今天可用,因为IE在IE兼容视图中呈现它;在IE8中按F12可以使用不同的模式播放。)
这真是难过;这真是伤心。看起来Firefox再次实现了字面意义,但毫无价值的实现赢得了微软有用的支持。还是我错过了新的getClientRects可以帮助开发人员的情况?
基于GuyPaddock从上面的回答,这似乎对我有用
function getLinesCount(element) {
var prevLH = element.style.lineHeight;
var factor = 1000;
element.style.lineHeight = factor + 'px';
var height = element.getBoundingClientRect().height;
element.style.lineHeight = prevLH;
return Math.floor(height / factor);
}
这里的技巧是增加行高,以至于“吞噬”浏览器/操作系统在呈现字体方面的任何差异
使用各种样式和不同的字体大小/系列来检查它,只是没有考虑到的事情(因为在我的情况下没关系)是填充-可以轻松将其添加到解决方案中。
不,不可靠。太多未知变量
清单继续。希望有一天,会有这样一种用JavaScript可靠地完成此任务的方法,但是直到那一天到来之前,您都运气不好。
我讨厌这些答案,希望有人能证明我错了。
您应该能够split('\ n')。length并得到换行符。
更新:这适用于FF / Chrome,但不适用于IE。
<html>
<head>
<script src="jquery-1.3.2.min.js"></script>
<script>
$(document).ready(function() {
var arr = $("div").text().split('\n');
for (var i = 0; i < arr.length; i++)
$("div").after(i + '=' + arr[i] + '<br/>');
});
</script>
</head>
<body>
<div>One
Two
Three</div>
</body>
</html>
getClientRects
返回客户端rects像这样,如果你想要得到的线,使用像后续的功能,这
function getRowRects(element) {
var rects = [],
clientRects = element.getClientRects(),
len = clientRects.length,
clientRect, top, rectsLen, rect, i;
for(i=0; i<len; i++) {
has = false;
rectsLen = rects.length;
clientRect = clientRects[i];
top = clientRect.top;
while(rectsLen--) {
rect = rects[rectsLen];
if (rect.top == top) {
has = true;
break;
}
}
if(has) {
rect.right = rect.right > clientRect.right ? rect.right : clientRect.right;
rect.width = rect.right - rect.left;
}
else {
rects.push({
top: clientRect.top,
right: clientRect.right,
bottom: clientRect.bottom,
left: clientRect.left,
width: clientRect.width,
height: clientRect.height
});
}
}
return rects;
}
开发HTML编辑器时,我找到了一种计算行号的方法。主要方法是:
在IE中,您可以调用getBoundingClientRects,它将每行返回为一个矩形
在webkit或新的标准html引擎中,它将返回每个元素或节点的客户端矩形,在这种情况下,您可以比较每个矩形,我的意思是每个矩形必须有一个最大的矩形,因此您可以忽略高度较小的那些矩形(如果有一个矩形的顶部小于它,底部大于它,条件为真。)
因此,让我们看一下测试结果:
绿色矩形是每行中最大的矩形
红色矩形是选择边界
蓝色矩形是展开后从开始到选择的边界,我们看到它可能大于红色矩形,因此我们必须检查每个矩形的底部以限制它必须小于红色矩形的底部。
var lineCount = "?";
var rects;
if (window.getSelection) {
//Get all client rectangles from body start to selection, count those rectangles that has the max bottom and min top
var bounding = {};
var range = window.getSelection().getRangeAt(0);//As this is the demo code, I dont check the range count
bounding = range.getBoundingClientRect();//!!!GET BOUNDING BEFORE SET START!!!
//Get bounding and fix it , when the cursor is in the last character of lineCount, it may expand to the next lineCount.
var boundingTop = bounding.top;
var boundingBottom = bounding.bottom;
var node = range.startContainer;
if (node.nodeType !== 1) {
node = node.parentNode;
}
var style = window.getComputedStyle(node);
var lineHeight = parseInt(style.lineHeight);
if (!isNaN(lineHeight)) {
boundingBottom = boundingTop + lineHeight;
}
else {
var fontSize = parseInt(style.fontSize);
if (!isNaN(fontSize)) {
boundingBottom = boundingTop + fontSize;
}
}
range = range.cloneRange();
//Now we have enougn datas to compare
range.setStart(body, 0);
rects = range.getClientRects();
lineCount = 0;
var flags = {};//Mark a flags to avoid of check some repeat lines again
for (var i = 0; i < rects.length; i++) {
var rect = rects[i];
if (rect.width === 0 && rect.height === 0) {//Ignore zero rectangles
continue;
}
if (rect.bottom > boundingBottom) {//Check if current rectangle out of the real bounding of selection
break;
}
var top = rect.top;
var bottom = rect.bottom;
if (flags[top]) {
continue;
}
flags[top] = 1;
//Check if there is no rectangle contains this rectangle in vertical direction.
var succ = true;
for (var j = 0; j < rects.length; j++) {
var rect2 = rects[j];
if (j !== i && rect2.top < top && rect2.bottom > bottom) {
succ = false;
break;
}
}
//If succ, add lineCount 1
if (succ) {
lineCount++;
}
}
}
else if (editor.document.selection) {//IN IE8 getClientRects returns each single lineCount as a rectangle
var range = body.createTextRange();
range.setEndPoint("EndToEnd", range);
rects = range.getClientRects();
lineCount = rects.length;
}
//Now we get lineCount here
试试这个解决方案:
function calculateLineCount(element) {
var lineHeightBefore = element.css("line-height"),
boxSizing = element.css("box-sizing"),
height,
lineCount;
// Force the line height to a known value
element.css("line-height", "1px");
// Take a snapshot of the height
height = parseFloat(element.css("height"));
// Reset the line height
element.css("line-height", lineHeightBefore);
if (boxSizing == "border-box") {
// With "border-box", padding cuts into the content, so we have to subtract
// it out
var paddingTop = parseFloat(element.css("padding-top")),
paddingBottom = parseFloat(element.css("padding-bottom"));
height -= (paddingTop + paddingBottom);
}
// The height is the line count
lineCount = height;
return lineCount;
}
您可以在此处查看它的运行情况:https : //jsfiddle.net/u0r6avnt/
尝试调整页面上面板的大小(使页面右侧变宽或变短),然后再次运行以查看它可以可靠地确定有多少行。
这个问题比看起来要难,但是大多数困难来自两个方面:
文本渲染在浏览器中的级别太低,无法直接从JavaScript查询。即使是CSS ::一线伪选择不表现得很像其他选择做(你不能反其道而行,例如,将样式应用到所有但第一行)。
上下文在计算行数方面起着很大的作用。例如,如果未在目标元素的层次结构中显式设置line-height,则可能会将“ normal”作为行高返回。另外,该元素可能正在使用中box-sizing: border-box
,因此可能需要填充。
我的方法通过直接控制行高并将框大小调整方法考虑在内,从而最大程度地减少了#2,从而获得了更具确定性的结果。
在某些情况下,例如,链接跨越非对齐文本跨越多行,您可以使用以下方法获取行数和每行的每个坐标:
var rectCollection = object.getClientRects();
https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getClientRects
之所以可行,是因为每行即使略有不同也会有所不同。只要存在,渲染器就会将它们绘制为不同的“矩形”。
遵循@BobBrunius 2010的建议,我使用jQuery创建了它。毫无疑问,它可以进行改进,但可能会有所帮助。
$(document).ready(function() {
alert("Number of lines: " + getTextLinesNum($("#textbox")));
});
function getTextLinesNum($element) {
var originalHtml = $element.html();
var words = originalHtml.split(" ");
var linePositions = [];
// Wrap words in spans
for (var i in words) {
words[i] = "<span>" + words[i] + "</span>";
}
// Temporarily replace element content with spans. Layout should be identical.
$element.html(words.join(" "));
// Iterate through words and collect positions of text lines
$element.children("span").each(function () {
var lp = $(this).position().top;
if (linePositions.indexOf(lp) == -1) linePositions.push(lp);
});
// Revert to original html content
$element.html(originalHtml);
// Return number of text lines
return linePositions.length;
}
#textbox {
width: 200px;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="textbox">Lorem ipsum dolor sit amet, consectetuer adipiscing elit,
<br>sed diam nonummy</div>
您可以将元素高度和元素高度与 line-height: 0
function lineCount(elm) {
const style = elm.getAttribute('style')
elm.style.marginTop = 0
elm.style.marginBottom = 0
elm.style.paddingTop = 0
elm.style.paddingBottom = 0
const heightAllLine = elm.offsetHeight
elm.style.lineHeight = 0
const height1line = elm.offsetHeight
const lineCount = Math.round(heightAllLine / height1line)
elm.setAttribute('style', style)
if (isNaN(lineCount)) return 0
return lineCount
}