Как подсчитать текстовые строки внутри элемента DOM? Могу я? - PullRequest
106 голосов
/ 24 апреля 2009

Мне интересно, есть ли способ подсчета строк внутри div, например. Скажем, у нас есть div как:

<div id="content">hello how are you?</div>

В зависимости от многих факторов, div может содержать одну, две или даже четыре строки текста. Есть ли способ узнать сценарий?

Другими словами, представлены ли автоматические разрывы в DOM вообще?

Ответы [ 16 ]

72 голосов
/ 24 апреля 2009

Если размер 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");

Вам также нужно будет учитывать отступы и межстрочный интервал.

EDIT

Полностью автономный тест, явно устанавливающий высоту строки:

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>
17 голосов
/ 10 января 2010

Одно из решений заключается в том, чтобы заключить каждое слово в тег span, используя скрипт. Тогда, если размерность Y данного тега span меньше, чем у его непосредственного предшественника, тогда происходит разрыв строки.

12 голосов
/ 23 февраля 2015

Проверьте функцию getClientRects () , которую можно использовать для подсчета количества строк в элементе. Вот пример того, как его использовать.

var message_lines = $("#message_container")[0].getClientRects();

Возвращает объект DOM JavaScript. Количество строк можно узнать, выполнив это:

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>

Хотя я не рекомендую жестко программировать этот стиль. Это только для примера.

11 голосов
/ 04 июня 2016

Я не был удовлетворен ответами здесь и на другие вопросы. Ответ с наивысшим рейтингом не учитывает 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>
7 голосов
/ 26 февраля 2017

Клонируйте объект контейнера, напишите 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/

6 голосов
/ 16 февраля 2013

Для тех, кто использует 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);
}
5 голосов
/ 25 апреля 2009

Я убежден, что сейчас это невозможно. Это было, однако.

Реализация getClientRects в IE7 сделала именно то, что я хочу. Откройте эту страницу в 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 делает то же самое сейчас. (Страница Мартина Хоннена работает сегодня, потому что IE отображает ее в режиме сравнения IE; нажмите F12 в IE8, чтобы играть в разных режимах.)

Это грустно. Похоже, что буквальная, но бесполезная реализация Firefox спецификации выиграла у полезной Microsoft. Или я пропускаю ситуацию, когда новые getClientRects могут помочь разработчику?

3 голосов
/ 26 марта 2017

основываясь на ответе Гай Паддока сверху, мне кажется, это работает

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);
}

Хитрость в том, чтобы увеличить высоту строки настолько, чтобы она "проглотила" любые различия между браузером и ОС в способе отображения шрифтов

Проверено различными стилями и размерами шрифтов / семейств единственное, что не учитывается (поскольку в моем случае это не имело значения), это отступы, которые можно легко добавить в решение.

2 голосов
/ 24 апреля 2009

Нет, ненадежно. Просто слишком много неизвестных переменных

  1. Какая ОС (разные DPI, варианты шрифтов и т. Д.)?
  2. Размер шрифта у них увеличен, потому что они практически слепые?
  3. Черт, в браузерах webkit вы можете изменять размеры текстовых полей по своему желанию.

Список можно продолжить. Я надеюсь, что когда-нибудь появится такой способ надежного выполнения этого с помощью JavaScript, но пока этот день не наступит, вам не повезет.

Я ненавижу подобные ответы и надеюсь, что кто-то может доказать, что я неправ.

1 голос
/ 21 декабря 2016

Попробуйте это решение:

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/

Попробуйте изменить размеры панелей на странице (чтобы сделать правую сторону страницы шире или короче), а затем снова запустите ее, чтобы убедиться, что она может достоверно определить количество строк.

Эта проблема сложнее, чем кажется, но большая часть трудностей исходит из двух источников:

  1. Рендеринг текста слишком низкоуровневый в браузерах, чтобы напрямую запрашивать его из JavaScript. Даже псевдоселектор CSS :: first-line ведет себя не совсем так, как другие селекторы (его нельзя инвертировать, например, чтобы применить стилизацию ко всем , но к первой строке).

  2. Контекст играет большую роль в том, как вы вычисляете количество строк. Например, если line-height не было явно задано в иерархии целевого элемента, вы можете получить «normal» обратно как высоту строки. Кроме того, элемент может использовать box-sizing: border-box и поэтому может быть дополнен.

Мой подход сводит к минимуму # 2 путем непосредственного управления высотой строки и учета метода определения размеров ячеек, что приводит к более детерминированному результату.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...