Получить текст конкретной строчки

const Lines = (el, l, lines = [], last = 0, s = 0) => {

  el.append(cl = document.createElement('div'));
  el.textContent.split("").forEach(v => {
    cl.innerHTML += v;
    last != (last = cl.offsetHeight) && s++;
    lines[s] = (lines[s] ?? '') + v;
    if(lines[l+1])
      cl.remove();    
  });

console.log(lines[l]);
};

Lines(text, 3);
window.onresize = _ => Lines(text, 3);
#text {
 white-space: pre-wrap;
 max-width: 40%
}
<div id=text>    
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
 Praesentium nemo dolores debitis, maxime quia ipsum quasi 
officiis id libero tenetur autem similique iure itaque optio quis beatae minima! Libero, eaque!
</div>

Ни как не удается выхватить текст конкретной строчки. На выходе получаю текст но он то обрезан сначала, то сканца. Как мне решить это?

введите сюда описание изображения

В моем случаи вытаскивает

tur adipisicing elit.

Вместо

consectetur adipisicing elit.

Ответы (1 шт):

Автор решения: EzioMercer

Придумал такой алгоритм:

  1. Рзабиваем текст по пробелам

  2. Объявляем массив line и складываем туда по одному слова из разбиения

  3. Создаём временный div, куда каждый раз вводим объединение всех слов из line и смотрим на его ширину. Стили у div-а такие, чтобы при добавлении и удалении не было видно этого визуально. Не использовал display: none, т.к. тогда не будет размера у div-а, а так можно будет настроить ему такие же стили как у основного div-а и более корректно определять допустимую ширину и прочие данные

  4. Пока ширина меньше чем у основного div-а, то просто продолжаем добавлять слова. Если ширина станет больше чем у основного div-а, то объединяем все слова, кроме последнего в одну сроку и добавляем в массив строк

  5. Последнее слово сразу становится первым словом для следующего предложения

  6. После окончания цикла смотрим, если line, не пустой, значит осталось последнее предложение и его просто добавлем в массив lines

  7. Т.к. количество строк может меняться постоянно, то при отсутсвии строки под нужным индексом, просто возвращается последняя строка

const getLine = (target, index) => {
  const lines = [];
  const separatorSymbol = ' ';
  const words = target.textContent.trim().split(separatorSymbol);
  const targetWidth = target.offsetWidth;
  
  const tempDiv = document.createElement('div');
  tempDiv.style = 'visibility: hidden; position: absolute; width: fit-content';
  document.body.append(tempDiv);
  
  let line = [];
  
  for (const word of words) {
    line.push(word);
    
    tempDiv.innerHTML = line.join(separatorSymbol);
    
    const currWidth = tempDiv.offsetWidth;
    
    if (currWidth <= targetWidth) continue;
    
    const lastWord = line.pop();
    
    lines.push(line.join(separatorSymbol));
    
    line = [lastWord];
  }
  
  if (line.length !== 0) lines.push(line.join(separatorSymbol));
  
  tempDiv.remove();

  return lines[index] ?? lines[lines.length - 1];
};

console.log(getLine(text, 3));
window.onresize = _ => console.log(getLine(text, 3));
#text {
  white-space: pre-wrap;
  max-width: 40%
}
<div id=text>    
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Praesentium nemo dolores debitis, maxime quia ipsum quasi officiis id libero tenetur autem similique iure itaque optio quis beatae minima! Libero, eaque!
</div>

Код может показаться рабочим, но это далеко не так. Алгоритм будет неправильно работать например если вручную расставлять переносы строк или изменить правило переноса в основном div-е или ещё что-то. Универсального способа не придумал, но конкретно под эти правила можно этот алгоритм использовать

А ещё не нравится постоянно добавлять и удалять div из DOM-а, наверное точно зная шрифт и размеры каждого символа, можно просто вычислить ширину. Для небольшой оптимизации можно ещё объявление tempDiv и назначение стилей вынести за пределы getLine, чтобы каждый раз не создавать его

→ Ссылка