There is a .text-wrap block with a given size, there is an array of text strings in jQuery (of different lengths and padded). The task - when you click a button, enter random text into the block by adjusting its font size. There are no questions with random text, questions are precisely in adaptability =)

The first thing that came to mind:

In .text-wrap add another div with auto height and 100% width; it turns out so

 <div class=".text-wrap"> <div class = ".text"> Тут текстовая строка </div> </div> 

We add text with an obviously huge font size to the inner block and further reduce the font until the height of the inner one becomes less than the outer block.

Did through while , function works. But for some texts she makes 300-400 passes. Especially if the font reduction step is small. then decided to reduce through recursion and multiplier. About 13-15 steps per two-line text are obtained.

Here is the code:

 jQuery.noise = 15; //погрешность ресайза в пикс jQuery.step = 100; //шаг jQuery.startFontSize = 200; //стартовый размер шрифта jQuery.currentFontSize = 100; //текущий размер шрифта jQuery.stepCounter = 0; //счетчик действий jQuery.stepper = 1; //множитель шага шрифта (на это чилсо делим) function changeSizeDown(he1, block) //he1 - высота внешнего блока, block - блок с текстом { //если мы добились своего, заканчиваем рекурсию if(he1 - jQuery.noise < block.height() && block.height() < he1 + jQuery.noise) { //noise - погрешность высоты (т.к. 100% малый шанс попасть) return 1; } //иначе, если высота текста больше высоты блока else if(block.height() > he1) { jQuery.currentFontSize -= Math.ceil(jQuery.step/jQuery.stepper); console.log('Step: '+jQuery.stepCounter+' / Side: down / fsize: ' + jQuery.currentFontSize + ' / mult: x'+jQuery.stepper); console.log('Blocks: '+block.height()+' / ' + he1); block.css("font-size", jQuery.currentFontSize + "px"); changeSizeDown(he1, block); } //если высота блока меньше, то увеличиваем шрифт else if(block.height() < he1) { if(jQuery.stepper < 50) //если множитель шага < 50, то умножаем вдвое jQuery.stepper = jQuery.stepper*2; else //иначе мы уже подобрали максимально близкий размер шрифта, а шагов сделали слишком много. Поэтому стоп. return 0; jQuery.currentFontSize += Math.ceil(jQuery.step/jQuery.stepper); console.log('Step: '+jQuery.stepCounter+' / Side: up / fsize: ' + jQuery.currentFontSize + ' / mult: x'+jQuery.stepper); console.log('Blocks: '+block.height()+' / ' + he1); block.css("font-size", jQuery.currentFontSize + "px"); changeSizeDown(he1, block); } } 

This code quickly copes with its task. But, like the cycle, it sometimes works incorrectly on mobile devices. Namely, it changes its size once, does not change it once.

Can anyone have ideas or simpler solutions? Googled a lot. I fitText say that any fitText is not suitable for me, since they only repel the width. And I have set the width and height.

    1 answer 1

    So, if anyone is interested. Understood with most of his mistakes.

     jQuery.noise = 15; //погрешность ресайза в пикс jQuery.step = 100; //шаг размера шрифта в пикс jQuery.startFontSize = 200; //стартовый размер шрифта jQuery.currentFontSize = 200; //текущий размер шрифта jQuery.stepper = 1; //множитель jQuery.stopper = false; //стоппер function changeSize(he1, block) { //he1 - необходимая высота //block - div с текстом //если мы находимся в пределах допустимой погрешности, то все ок, завершаем работу или если поступила команда стопера if(he1 - jQuery.noise < block.height() && block.height() < he1 + jQuery.noise || jQuery.stopper == true) { block.css('line-height', jQuery.currentFontSize + (jQuery.currentFontSize/10) + 'px'); //высота строки (настройте под себя) var padding = (he1 - block.height())/2 + "px"; // т.к. у нас есть погрешность, остатки я выравниваю за счет отступов block.css('padding-top', padding); block.css('padding-bottom', padding); //тут и была моя первая ошибка. Я не обнулял счетчики =)) jQuery.stopper = false; jQuery.stepCounter = 0; jQuery.stepper = 1; return 1; } //если высота блока больше чем необходимая, уменьшаем else if(block.height() > he1) { //уменьшаем размер шрифта на шаг / множитель jQuery.currentFontSize -= Math.ceil(jQuery.step/jQuery.stepper); block.css("font-size", jQuery.currentFontSize + "px"); return changeSizeDown(he1, block); //рекурсия } //если высота блока меньше чем необходимая, увеличиваем (и увеличиваем вдвое stepper) else if(block.height() < he1) { //тут ограничитель множителя. Методом проб и ошибок выяснилось, что для моих нужд множитель более 50 - излишне. Когда множитель больше 50 мы уже очень близки к нужному размеру, потому тормозим скрипт. Иначе умножаем вдвое if(jQuery.stepper < 50) jQuery.stepper = jQuery.stepper*2; else{ jQuery.stopper = true; return changeSizeDown(he1, block); } jQuery.currentFontSize += Math.ceil(jQuery.step/jQuery.stepper); block.css("font-size", jQuery.currentFontSize + "px"); return changeSizeDown(he1, block); //рекурсия } } 

    Before calling the script, you must:

    1. assign a starting font size to the block.
    2. Make the row height normal. line-height:normal
    3. remove padding

    My example call:

     //при загрузке страницы $(window).load(function() { updateAdvice(); }); //при ресайзе страницы. Выполняем только, когда ресайз закончил. За это отвечает функция debouncer function debouncer(func, timeout) { var timeoutID, timeout = timeout || 200; return function() { var scope = this, args = arguments; clearTimeout(timeoutID); timeoutID = setTimeout(function() { func.apply(scope, Array.prototype.slice.call(args)); }, timeout); } } $(window).resize(debouncer(function(e) { adapt(); })); //Переменные jQuery.noise = 15; //погрешность ресайза в пикс jQuery.step = 100; //шаг jQuery.startFontSize = 200; //стартовый размер шрифта jQuery.currentFontSize = 200; //текущий размер шрифта jQuery.stepper = 1; //множитель jQuery.lastAd = 0; jQuery.stopper = false; //ТЕКСТ (для примера взят с http://fucking-great-advice.ru/ ) jQuery.adv = ['Не опускай руки!', 'Не делай плохого!', 'Упал — отряхнись!', 'Соблюдай режим!', 'Группируй задачи!', 'Не срывай сроки!', 'Мысли масштабнее!', 'Учись готовить!', 'Признавай свои ошибки!']; //Замена текста function updateAdvice() { $('.text').text(jQuery.adv[rand(jQuery.adv.length)]); adapt(); } //ФУНКЦИЯ РАНДОМНОГО ЧИСЛА// function rand(max) { var rand = jQuery.lastAd; while (rand == jQuery.lastAd) { rand = Math.random() * (max - 1); rand = Math.round(rand); } jQuery.lastAd = rand; return rand; } //АДАПТАЦИЯ function adapt() { //Обнуляем все $('.text').css('opacity', '0'); $('.text').css('padding-top', '0px'); $('.text').css('padding-bottom', '0px'); $('.text').css("font-size", jQuery.startFontSize + "px"); $('.text').css('line-height', 'normal'); jQuery.currentFontSize = jQuery.startFontSize; //стартуем changeSizeDown($('.text-wrap').height(), $('.text')) } function changeSizeDown(he1, block) { jQuery.stepCounter++; //счетчик действий if (jQuery.stepCounter > 50) { updateAdvice(); return 0; }; //если мы находимся в пределах допустимой погрешности, то все ок, завершаем работу if (he1 - jQuery.noise < block.height() && block.height() < he1 + jQuery.noise || jQuery.stopper == true) { block.css('line-height', jQuery.currentFontSize + (jQuery.currentFontSize / 10) + 'px'); var padding = (he1 - block.height()) / 2 + "px"; block.css('padding-top', padding); block.css('padding-bottom', padding); block.animate({ opacity: 1, }, 300); jQuery.stopper = false; jQuery.stepCounter = 0; jQuery.stepper = 1; return 1; } //если высота блока больше чем необходимая, уменьшаем else if (block.height() > he1) { jQuery.currentFontSize -= Math.ceil(jQuery.step / jQuery.stepper); block.css("font-size", jQuery.currentFontSize + "px"); return changeSizeDown(he1, block); } //если высота блока меньше чем необходимая, увеличиваем (и увеличиваем вдвое stepper) else if (block.height() < he1) { if (jQuery.stepper < 50) jQuery.stepper = jQuery.stepper * 2; else { jQuery.stopper = true; return changeSizeDown(he1, block); } jQuery.currentFontSize += Math.ceil(jQuery.step / jQuery.stepper); block.css("font-size", jQuery.currentFontSize + "px"); return changeSizeDown(he1, block); } } //КНОПКА// $('.button').on('click', function() { updateAdvice(); }); 
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class='text-wrap' style="width: 400px; height: 300px; background-color: #d8d8d8;"> <div class='text'> sdfsdfef </div> </div> <div class='button'>Поменять</div> 

    • the word "bigger" does not fit - Grundy
    • Yes, there is still a lot that needs to be improved) In this case, the width test is Alexandr Opekunov