回答:
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')
1つの解決策は、スクリプトを使用してすべての単語を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("");
いくつかの注意点は、それが含まれている要素がインラインの場合にのみ機能することですが、含まれているインライン要素をブロック要素で囲んで幅を制御することもできます。
<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、モノラル、コミック、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
すべてのブラウザで動作し、標準外のまれな機能はありません。
チェック:https : //jsfiddle.net/gzceamtr/
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は常に要素ごとに1つのクライアント四角形を返しますが、IE8は同じことを行います。(Martin Honnenのページは、IEがIE互換ビューで表示するため、今日機能します。IE8でF12を押して、さまざまなモードで再生します。)
これは悲しいです。再びFirefoxのリテラルのように見えますが、仕様の無価値な実装がMicrosoftの便利な仕様に勝っています。または、新しい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);
}
ここでの秘訣は、ブラウザ/ OSの違いがフォントをレンダリングする方法で "飲み込む"ように行の高さを増やすことです。
さまざまなスタイリングとさまざまなフォントサイズ/ファミリで確認したところ、考慮されないのは(私の場合は問題ではないため)パディングです。これは簡単にソリューションに追加できます。
いいえ、確実ではありません。単に未知の変数が多すぎる
リストは続きます。いつか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エンジンでは、各要素またはノードのクライアントの四角形を返します。この場合、各四角形を比較できます。つまり、それぞれの四角形が最大でなければならないため、高さが小さい方の四角形を無視できます(if長方形の上部がそれよりも小さく、底部がそれよりも大きい場合、条件はtrueです。)
テスト結果を見てみましょう:
緑の長方形は各行の最大の長方形です
赤い長方形は選択境界です
青い長方形は、展開後の開始から選択までの境界です。赤い長方形よりも大きくなる可能性があるため、各長方形の底をチェックして、赤い長方形の底よりも小さくなければならないことを制限する必要があります。
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/
ページのパネルのサイズを変更して(ページの右側を広くしたり短くしたり)、もう一度実行して、行数が確実にわかることを確認してください。
この問題は見かけよりも難しいですが、ほとんどの問題は2つの原因に起因します。
ブラウザでのテキストレンダリングは低レベルすぎて、JavaScriptから直接クエリすることはできません。他のセレクタは、(あなたがすべてにスタイリング適用するには、例えば、それを反転することができないんかなりのようにもCSS :: first-line擬似セレクタは動作しませんが、最初の行)。
行数の計算方法では、コンテキストが大きな役割を果たします。たとえば、ターゲット要素の階層でline-heightが明示的に設定されていなかった場合、「通常」が行の高さとして返される可能性があります。さらに、要素が使用されている可能性があるbox-sizing: border-box
ため、パディングが行われる可能性があります。
私のアプローチでは、行の高さを直接制御し、ボックスのサイズ設定方法を考慮に入れることにより、#2を最小限に抑え、より確定的な結果をもたらします。
正当化されていないテキストの複数の行にまたがるリンクのように、これを使用すると、行数と各行のすべての座標を取得できる場合があります。
var rectCollection = object.getClientRects();
https://developer.mozilla.org/en-US/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
}