Как отрегулировать шрифты, чтобы максимально соответствовать ширине и высоте textarea?

Я ввожу текст в textarea. Я хочу, чтобы шрифт был настроен динамически таким образом, чтобы текст заполнил доступный textarea с типом как можно больше. Для этого я использую стиль span с display:none в фоновом режиме для измерения ширины текущего введенного текста и масштабирования его до доступной ширины. У меня проблемы с логикой и браузером:

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

Рабочая скрипта, иллюстрирующая идею.

Как мне настроить так, чтобы текстовое поле заполнялось как можно больше как по ширине, так и по высоте?

Ответ 1

Трудная часть - это алгоритм для того, чтобы уменьшить размер шрифта. Здесь два решения. первый - самый уродливый код, который вы когда-либо видели (извините, 4:30 здесь, и я устал), но это демонстрирует решение, рекурсивные функции

$(document).ready(function() {
  var textAreaHeight = $('#inp').height();
  var fontSize = 200;
  var font = fontSize + "px";

  $('#inp').css("font-size", font);
  $('.hidden').css("font-size", font);

  $('#inp').keyup(function() {
    var txt = $(this).val();
    $('#hiddenSpan').html(txt);

    fontSize = decreaseFontSize(fontSize);
    font = fontSize + 'px';

    $('#inp').css("font-size", fontSize + 'px');
  })

  function decreaseFontSize(tempFontSize) {
    var textHeight = $('#hiddenSpan').height();
    if (textHeight > textAreaHeight) {
      var factor = .99; /* Arbitrary scaling factor */
      tempFontSize *= factor;
      $('#hiddenSpan').css("font-size", tempFontSize + 'px');

      return decreaseFontSize(tempFontSize);
    } else {
      return tempFontSize;
    }
  }
})

second one является более чистым, но просто добавляет еще одну строку, когда вы достигаете конца.

$(document).ready(function() {
    var textAreaHeight = $('#inp').height();
    var fontSize = 200;
    var inputLength = 0;
    var font = fontSize + "px"

    $('#inp').css("font-size", font);
    $('.hidden').css("font-size", font);

    $('#inp').keyup(function() {
        var txt = $(this).val();
        $('#hiddenSpan').html(txt);

        var textHeight = $('#hiddenSpan').height();

        if( textHeight > textAreaHeight ) {
            var font = decreaseFontSize( textHeight) + "px";
            $(this).css("font-size", font);
            $('.hidden').css("font-size", font);
        }
    })

    function decreaseFontSize( textHeight) {
        fontSize = textAreaHeight/(textHeight/fontSize); /* textHeight / fontSize will tell you how many rows are currently in the #hiddenSpan and will then fit those rows inside the height of the textArea */
        return fontSize;
    }
})

Теперь, действительно, основная часть ответа, которая делает оба этих решения, заключается в том, что я добавил это к вашему #hiddenSpan

#hiddenSpan {
  max-width: 300px; /* Makes the text wrap like the input box */
  display: inline-block; 
  word-wrap: break-word; /* Paired with display, allows the text to wrap */
  font-family: "Times New Roman", Times, serif; /* Added the same font to both elements so that they could actually be coordinated */
} 

После тестирования обоих из них с таким количеством символов, как мои маленькие пальцы могли собраться, я заметил, что рекурсивная функция немного улучшена, но не так сильно, как вы думаете.