sourcecode

고정 크기 컨테이너를 채우도록 동적 텍스트 자동 크기 조정

copyscript 2023. 5. 9. 22:54
반응형

고정 크기 컨테이너를 채우도록 동적 텍스트 자동 크기 조정

사용자가 입력한 텍스트를 고정된 크기의 div로 표시해야 합니다.제가 원하는 것은 글자 크기가 자동으로 조정되어 텍스트가 상자를 최대한 채우도록 하는 것입니다.

따라서 - div가 400pxx300px인 경우.만약 누군가가 ABC에 들어간다면 그것은 정말 큰 폰트입니다.만약 그들이 한 단락을 입력한다면, 그것은 작은 글꼴이 될 것입니다.

아마도 최대 글꼴 크기(32px)로 시작하고 텍스트가 너무 커서 컨테이너에 맞지 않을 때까지 글꼴 크기를 줄입니다.

이것이 바로 제가 하게 된 것입니다.

다음은 플러그인에 대한 링크입니다. https://plugins.jquery.com/textfill/
소스 링크: http://jquery-textfill.github.io/

;(function($) {
    $.fn.textfill = function(options) {
        var fontSize = options.maxFontPixels;
        var ourText = $('span:visible:first', this);
        var maxHeight = $(this).height();
        var maxWidth = $(this).width();
        var textHeight;
        var textWidth;
        do {
            ourText.css('font-size', fontSize);
            textHeight = ourText.height();
            textWidth = ourText.width();
            fontSize = fontSize - 1;
        } while ((textHeight > maxHeight || textWidth > maxWidth) && fontSize > 3);
        return this;
    }
})(jQuery);

$(document).ready(function() {
    $('.jtextfill').textfill({ maxFontPixels: 36 });
});

그리고 제 HTML은 이렇습니다.

<div class='jtextfill' style='width:100px;height:50px;'>
    <span>My Text Here</span>
</div>

저는 이전의 어떤 해결책도 성능이 좋지 않아서 루프 대신 간단한 수학을 사용하는 저만의 해결책을 만들었습니다.모든 브라우저에서도 잘 작동할 것입니다.

성능 테스트 사례에 따르면 여기에 있는 다른 솔루션보다 훨씬 빠릅니다.

(function($) {
    $.fn.textfill = function(maxFontSize) {
        maxFontSize = parseInt(maxFontSize, 10);
        return this.each(function(){
            var ourText = $("span", this),
                parent = ourText.parent(),
                maxHeight = parent.height(),
                maxWidth = parent.width(),
                fontSize = parseInt(ourText.css("fontSize"), 10),
                multiplier = maxWidth/ourText.width(),
                newSize = (fontSize*(multiplier-0.1));
            ourText.css(
                "fontSize", 
                (maxFontSize > 0 && newSize > maxFontSize) ? 
                    maxFontSize : 
                    newSize
            );
        });
    };
})(jQuery);

만약 당신이 기여하고 싶다면, 나는 이것을 Gist에 추가했습니다.

저는 이 답변에 대해 가끔 투표하는 것을 좋아하지만(감사합니다!), 이것은 정말로 이 문제에 대한 최고의 접근법은 아닙니다.여기에 있는 다른 멋진 답변들, 특히 반복하지 않고 해결책을 찾은 답변들을 확인해 보세요.


그래도 참고를 위해 제 원래 대답은 이렇습니다.

<html>
<head>
<style type="text/css">
    #dynamicDiv
    {
    background: #CCCCCC;
    width: 300px;
    height: 100px;
    font-size: 64px;
    overflow: hidden;
    }
</style>

<script type="text/javascript">
    function shrink()
    {
        var textSpan = document.getElementById("dynamicSpan");
        var textDiv = document.getElementById("dynamicDiv");

        textSpan.style.fontSize = 64;

        while(textSpan.offsetHeight > textDiv.offsetHeight)
        {
            textSpan.style.fontSize = parseInt(textSpan.style.fontSize) - 1;
        }
    }
</script>

</head>
<body onload="shrink()">
    <div id="dynamicDiv"><span id="dynamicSpan">DYNAMIC FONT</span></div>
</body>
</html>

클래스가 포함된 버전은 다음과 같습니다.

<html>
<head>
<style type="text/css">
.dynamicDiv
{
    background: #CCCCCC;
    width: 300px;
    height: 100px;
    font-size: 64px;
    overflow: hidden;
}
</style>

<script type="text/javascript">
    function shrink()
    {
        var textDivs = document.getElementsByClassName("dynamicDiv");
        var textDivsLength = textDivs.length;

        // Loop through all of the dynamic divs on the page
        for(var i=0; i<textDivsLength; i++) {

            var textDiv = textDivs[i];

            // Loop through all of the dynamic spans within the div
            var textSpan = textDiv.getElementsByClassName("dynamicSpan")[0];

            // Use the same looping logic as before
            textSpan.style.fontSize = 64;

            while(textSpan.offsetHeight > textDiv.offsetHeight)
            {
                textSpan.style.fontSize = parseInt(textSpan.style.fontSize) - 1;
            }

        }

    }
</script>

</head>
<body onload="shrink()">
    <div class="dynamicDiv"><span class="dynamicSpan">DYNAMIC FONT</span></div>
    <div class="dynamicDiv"><span class="dynamicSpan">ANOTHER DYNAMIC FONT</span></div>
    <div class="dynamicDiv"><span class="dynamicSpan">AND YET ANOTHER DYNAMIC FONT</span></div>
</body>
</html>

대부분의 다른 답변은 루프를 사용하여 div에 맞을 때까지 글꼴 크기를 줄입니다. 글꼴 크기가 바뀔 때마다 페이지가 요소를 다시 렌더링해야 하기 때문에 매우 느립니다.저는 결국 사용자 브라우저를 정지시키지 않고 주기적으로 내용을 업데이트할 수 있는 방식으로 수행하기 위해 자체 알고리즘을 작성해야 했습니다.몇 가지 다른 기능(텍스트 회전, 패딩 추가)을 추가하고 jQuery 플러그인으로 패키지화했습니다. 다음 위치에서 얻을 수 있습니다.

https://github.com/DanielHoffmann/jquery-bigtext

간단히 말하면

$("#text").bigText();

그리고 그것은 당신의 용기에 잘 맞을 것입니다.

여기에서 실제로 보기:

http://danielhoffmann.github.io/jquery-bigtext/

현재로서는 div의 높이와 너비가 고정되어 있어야 하며 텍스트를 여러 줄로 묶을 수 없습니다.

최대 글꼴 크기를 설정할 수 있는 옵션을 얻는 작업을 할 것입니다.

편집: 플러그인에 몇 가지 문제가 더 있습니다. 플러그인은 표준 모델 외에 다른 박스 모델을 처리하지 않으며 디비에는 여백이나 테두리가 있을 수 없습니다.제가 작업을 해보겠습니다.

Edit2: 이제 이러한 문제와 제한 사항을 수정하고 옵션을 추가했습니다.최대 글꼴 크기를 설정할 수 있으며 너비, 높이 또는 둘 모두를 사용하여 글꼴 크기를 제한하도록 선택할 수도 있습니다.래퍼 요소에서 최대 너비 및 최대 높이 값을 수락하는 작업을 수행할 것입니다.

편집 3: 플러그인을 버전 1.2.0으로 업데이트했습니다.코드 및 새로운 옵션(수직 정렬, 수평 정렬, 텍스트 정렬)에 대한 대대적인 정리 및 스팬 태그 내부의 내부 요소(예: 줄 바꿈 또는 글꼴 모음 아이콘)에 대한 지원.

이것은 위에 Geeky Monkey가 게시한 내용을 기반으로 하며 일부 수정 사항이 있습니다.

; (function($) {
/**
* Resize inner element to fit the outer element
* @author Some modifications by Sandstrom
* @author Code based on earlier works by Russ Painter (WebDesign@GeekyMonkey.com)
* @version 0.2
*/
$.fn.textfill = function(options) {

    options = jQuery.extend({
        maxFontSize: null,
        minFontSize: 8,
        step: 1
    }, options);

    return this.each(function() {

        var innerElements = $(this).children(':visible'),
            fontSize = options.maxFontSize || innerElements.css("font-size"), // use current font-size by default
            maxHeight = $(this).height(),
            maxWidth = $(this).width(),
            innerHeight,
            innerWidth;

        do {

            innerElements.css('font-size', fontSize);

            // use the combined height of all children, eg. multiple <p> elements.
            innerHeight = $.map(innerElements, function(e) {
                return $(e).outerHeight();
            }).reduce(function(p, c) {
                return p + c;
            }, 0);

            innerWidth = innerElements.outerWidth(); // assumes that all inner elements have the same width
            fontSize = fontSize - options.step;

        } while ((innerHeight > maxHeight || innerWidth > maxWidth) && fontSize > options.minFontSize);

    });

};

})(jQuery);

이진 검색을 사용하여 가장 적은 단계로 부모에 맞는 최대 크기를 찾는 향상된 루프 방법이 있습니다(고정 글꼴 크기로 스텝을 밟는 것보다 빠르고 정확함).또한 코드는 성능을 위해 여러 가지 방법으로 최적화되어 있습니다.

기본적으로 10개의 이진 검색 단계가 수행되며, 이 단계는 최적 크기의 0.1% 이내가 됩니다.대신 numIter를 일부 값 N으로 설정하여 최적 크기의 1/2^N 이내로 만들 수 있습니다.

CSS 셀렉터와 함께 호출합니다. 예: fitToParent('.title-span');

/**
 * Fit all elements matching a given CSS selector to their parent elements'
 * width and height, by adjusting the font-size attribute to be as large as
 * possible. Uses binary search.
 */
var fitToParent = function(selector) {
    var numIter = 10;  // Number of binary search iterations
    var regexp = /\d+(\.\d+)?/;
    var fontSize = function(elem) {
        var match = elem.css('font-size').match(regexp);
        var size = match == null ? 16 : parseFloat(match[0]);
        return isNaN(size) ? 16 : size;
    }
    $(selector).each(function() {
        var elem = $(this);
        var parentWidth = elem.parent().width();
        var parentHeight = elem.parent().height();
        if (elem.width() > parentWidth || elem.height() > parentHeight) {
            var maxSize = fontSize(elem), minSize = 0.1;
            for (var i = 0; i < numIter; i++) {
                var currSize = (minSize + maxSize) / 2;
                elem.css('font-size', currSize);
                if (elem.width() > parentWidth || elem.height() > parentHeight) {
                    maxSize = currSize;
                } else {
                    minSize = currSize;
                }
            }
            elem.css('font-size', minSize);
        }
    });
};

Angular에 대한 지침을 만들었습니다.JS - 기키 몽키의 대답에 크게 영감을 받았지만 jQuery 의존성은 없었습니다.

데모: http://plnkr.co/edit/8tPCZIjvO3VSApSeTtYr?p=preview

마크업

<div class="fittext" max-font-size="50" text="Your text goes here..."></div>

지시문

app.directive('fittext', function() {

  return {
    scope: {
      minFontSize: '@',
      maxFontSize: '@',
      text: '='
    },
    restrict: 'C',
    transclude: true,
    template: '<div ng-transclude class="textContainer" ng-bind="text"></div>',
    controller: function($scope, $element, $attrs) {
      var fontSize = $scope.maxFontSize || 50;
      var minFontSize = $scope.minFontSize || 8;

      // text container
      var textContainer = $element[0].querySelector('.textContainer');

      angular.element(textContainer).css('word-wrap', 'break-word');

      // max dimensions for text container
      var maxHeight = $element[0].offsetHeight;
      var maxWidth = $element[0].offsetWidth;

      var textContainerHeight;
      var textContainerWidth;      

      var resizeText = function(){
        do {
          // set new font size and determine resulting dimensions
          textContainer.style.fontSize = fontSize + 'px';
          textContainerHeight = textContainer.offsetHeight;
          textContainerWidth = textContainer.offsetWidth;

          // shrink font size
          var ratioHeight = Math.floor(textContainerHeight / maxHeight);
          var ratioWidth = Math.floor(textContainerWidth / maxWidth);
          var shrinkFactor = ratioHeight > ratioWidth ? ratioHeight : ratioWidth;
          fontSize -= shrinkFactor;

        } while ((textContainerHeight > maxHeight || textContainerWidth > maxWidth) && fontSize > minFontSize);        
      };

      // watch for changes to text
      $scope.$watch('text', function(newText, oldText){
        if(newText === undefined) return;

        // text was deleted
        if(oldText !== undefined && newText.length < oldText.length){
          fontSize = $scope.maxFontSize;
        }
        resizeText();
      });
    }
  };
});

저는 위의 스크립트를 Marcus Ekwall: https://gist.github.com/3945316 에서 포크하여 제 기본 설정에 맞게 조정했습니다. 이제 창 크기가 조정되면 시작되므로 아이가 항상 용기에 맞도록 합니다.참고를 위해 아래 스크립트를 붙여 놓았습니다.

(function($) {
    $.fn.textfill = function(maxFontSize) {
        maxFontSize = parseInt(maxFontSize, 10);
        return this.each(function(){
            var ourText = $("span", this);
            function resizefont(){
                var parent = ourText.parent(),
                maxHeight = parent.height(),
                maxWidth = parent.width(),
                fontSize = parseInt(ourText.css("fontSize"), 10),
                multiplier = maxWidth/ourText.width(),
                newSize = (fontSize*(multiplier));
                ourText.css("fontSize", maxFontSize > 0 && newSize > maxFontSize ? maxFontSize : newSize );
            }
            $(window).resize(function(){
                resizefont();
            });
            resizefont();
        });
    };
})(jQuery);

OP의 답변에 대한 저의 수정 사항입니다.

간단히 말해서, 이를 최적화하기 위해 노력한 많은 사람들은 루프가 사용되고 있다고 불평했습니다.예, 루프는 느릴 수 있지만 다른 접근 방식은 부정확할 수 있습니다.

따라서 최적의 글꼴 크기를 찾기 위해 이진 검색을 사용합니다.

$.fn.textfill = function()
{
    var self = $(this);
    var parent = self.parent();

    var attr = self.attr('max-font-size');
    var maxFontSize = parseInt(attr, 10);
    var unit = attr.replace(maxFontSize, "");

    var minFontSize = parseInt(self.attr('min-font-size').replace(unit, ""));
    var fontSize = (maxFontSize + minFontSize) / 2;

    var maxHeight = parent.height();
    var maxWidth = parent.width();

    var textHeight;
    var textWidth;

    do
    {
        self.css('font-size', fontSize + unit);

        textHeight = self.height();
        textWidth = self.width();

        if(textHeight > maxHeight || textWidth > maxWidth)
        {
            maxFontSize = fontSize;
            fontSize = Math.floor((fontSize + minFontSize) / 2);
        }
        else if(textHeight < maxHeight || textWidth < maxWidth)
        {
            minFontSize = fontSize;
            fontSize = Math.floor((fontSize + maxFontSize) / 2);
        }
        else
            break;

    }
    while(maxFontSize - minFontSize > 1 && maxFontSize > minFontSize);

    self.css('font-size', fontSize + unit);

    return this;
}

function resizeText()
{
  $(".textfill").textfill();
}

$(document).ready(resizeText);
$(window).resize(resizeText);

또한 요소는 최소 및 최대 글꼴을 지정할 수 있습니다.

<div class="container">
    <div class="textfill" min-font-size="10px" max-font-size="72px">
        Text that will fill the container, to the best of its abilities, and it will <i>never</i> have overflow.
    </div>
</div>

게다가, 이 알고리즘은 단위가 없습니다.를 지정할 수 .em,rem,%등을 사용하여 최종 결과를 얻을 수 있습니다.

Fiddle은 다음과 같습니다. https://jsfiddle.net/fkhqhnqe/1/

제 웹사이트에도 똑같은 문제가 있었습니다.저는 프로젝터, 벽, 큰 화면에 표시되는 페이지를 가지고 있습니다.

제 폰트의 최대 크기를 모르기 때문에, 저는 @GeekMonkey의 위 플러그인을 재사용했지만 폰트 크기를 늘렸습니다.

$.fn.textfill = function(options) {
        var defaults = { innerTag: 'span', padding: '10' };
        var Opts = jQuery.extend(defaults, options);

        return this.each(function() {
            var ourText = $(Opts.innerTag + ':visible:first', this);
            var fontSize = parseFloat(ourText.css('font-size'),10);
            var doNotTrepass = $(this).height()-2*Opts.padding ;
            var textHeight;

            do {
                ourText.css('font-size', fontSize);
                textHeight = ourText.height();
                fontSize = fontSize + 2;
            } while (textHeight < doNotTrepass );
        });
    };

제안된 반복 솔루션은 다음과 같은 두 가지 측면에서 속도를 크게 높일 수 있습니다.

글꼴 크기에 1을 더하거나 빼는 대신 상수를 곱합니다.

첫째, 코스 상수를 사용할 때 0을 사용합니다. 예를 들어, 각 루프의 크기를 두 배로 늘립니다.그런 다음, 어디서부터 시작해야 할지 대략적인 아이디어를 가지고 같은 일을 더 세밀하게 조정합니다. 예를 들어, 1.1을 곱합니다.완벽주의자는 이상적인 글꼴의 정확한 정수 픽셀 크기를 원할 수 있지만 대부분의 관찰자는 100과 110 픽셀 사이의 차이를 알아차리지 못합니다.만약 당신이 완벽주의자라면, 훨씬 더 미세한 조정으로 세 번째를 반복하세요.

정확한 질문에 답하는 특정 루틴이나 플러그인을 작성하기보다는 기본적인 아이디어에 의존하고 코드의 변형을 작성하여 적합한 div, 스팬, 이미지 등 텍스트뿐만 아니라 모든 종류의 레이아웃 문제를 처리합니다.폭, 높이, 면적,...컨테이너 내에서 다른 요소와 일치하는 중...

다음은 예입니다.

  var                           nWindowH_px             = jQuery(window).height();
  var                           nWas                    = 0;
  var                           nTry                    = 5;

  do{
   nWas = nTry;
   nTry *= 2;
   jQuery('#divTitle').css('font-size' ,nTry +'px');
  }while( jQuery('#divTitle').height() < nWindowH_px );

  nTry = nWas;

  do{
   nWas = nTry;
   nTry = Math.floor( nTry * 1.1 );
   jQuery('#divTitle').css('font-size' ,nTry +'px');
  }while( nWas != nTry   &&   jQuery('#divTitle').height() < nWindowH_px );

  jQuery('#divTitle').css('font-size' ,nWas +'px');

다음은 minFontSize 매개 변수를 사용할 수 있는 허용된 응답 버전입니다.

(function($) {
    /**
    * Resizes an inner element's font so that the inner element completely fills the outer element.
    * @author Russ Painter WebDesign@GeekyMonkey.com
    * @author Blake Robertson 
    * @version 0.2 -- Modified it so a min font parameter can be specified.
    *    
    * @param {Object} Options which are maxFontPixels (default=40), innerTag (default='span')
    * @return All outer elements processed
    * @example <div class='mybigdiv filltext'><span>My Text To Resize</span></div>
    */
    $.fn.textfill = function(options) {
        var defaults = {
            maxFontPixels: 40,
            minFontPixels: 10,
            innerTag: 'span'
        };
        var Opts = jQuery.extend(defaults, options);
        return this.each(function() {
            var fontSize = Opts.maxFontPixels;
            var ourText = $(Opts.innerTag + ':visible:first', this);
            var maxHeight = $(this).height();
            var maxWidth = $(this).width();
            var textHeight;
            var textWidth;
            do {
                ourText.css('font-size', fontSize);
                textHeight = ourText.height();
                textWidth = ourText.width();
                fontSize = fontSize - 1;
            } while ((textHeight > maxHeight || textWidth > maxWidth) && fontSize > Opts.minFontPixels);
        });
    };
})(jQuery);

FitText.js(github 페이지)를 사용하여 이 문제를 해결할 수 있습니다.텍스트 채우기에 비해 매우 작고 효율적입니다.TextFill은 비싼 반면 루프를 사용하고 FitText는 사용하지 않습니다.

또한 FitText는 더 유연합니다(저는 매우 특별한 요구 사항이 있는 프로젝트에서 사용하며 챔피언처럼 작동합니다!).

HTML:

<div class="container">
  <h1 id="responsive_headline">Your fancy title</h1>
</div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="jquery.fittext.js"></script>
<script>
  jQuery("#responsive_headline").fitText();
</script>

옵션을 설정할 수도 있습니다.

<script>
  jQuery("#responsive_headline").fitText(1, { minFontSize: '30px', maxFontSize: '90px'});
</script>

CSS:

#responsive_headline {
   width: 100%;
   display: block;
}

필요한 경우 FitText에도 no-jQuery 버전이 있습니다.

편집: 이 코드는 HTML5 비디오 위에 노트를 표시하는 데 사용되었습니다.비디오 크기가 조정될 때(브라우저 창 크기가 조정될 때) 즉시 글꼴 크기를 변경합니다.노트는 비디오에 연결되어 있습니다(YouTube의 노트와 마찬가지로). 그래서 코드는 DOM 핸들 대신 인스턴스를 직접 사용합니다.

요청에 따라 이를 달성하기 위해 사용한 코드를 제출하겠습니다. (HTML5 비디오 위의 텍스트 상자)코드는 오래 전에 작성되었고, 저는 솔직히 그것이 꽤 지저분하다고 생각합니다.질문은 이미 답변이 되었고 답변은 오래전에 이미 받아들여졌기 때문에 저는 이것을 다시 쓰는 것을 귀찮아하지 않습니다.하지만 이를 단순화하고 싶은 사람이 있다면 언제든지 환영합니다!

// Figure out the text size:
var text = val['text'];
var letters = text.length;
var findMultiplier = function(x) { // g(x)
    /* By analysing some functions with regression, the resulting function that
     gives the best font size with respect to the number of letters and the size
     of the note is:
     g(x) = 8.3 - 2.75x^0.15 [1 < x < 255]
     f(x) = g(letters) * (x / 1000)^0.5
     Font size = f(size)
     */
    return 8.3 - 2.75 * Math.pow(x, 0.15);
};

var findFontSize = function(x) { // f(x)
    return findMultiplier(letters) * Math.pow(x / 1000, 0.5);
};

val.setFontSizeListener = function() {
    p.style.fontSize = '1px'; // So the text should not overflow the box when measuring.
    var noteStyle = window.getComputedStyle(table);
    var width = noteStyle.getPropertyValue('width');
    var height = noteStyle.getPropertyValue('height');
    var size = width.substring(0, width.length - 2) * height.substring(0, height.length - 2);
    p.style.fontSize = findFontSize(size) + 'px';
};
window.addEventListener('resize', val.setFontSizeListener);

이러한 숫자를 글꼴 계열에서 글꼴 계열로 조정해야 합니다.이것을 하는 좋은 방법은 GeoGebra라고 불리는 무료 그래프 비주얼라이저를 다운로드하는 것입니다.텍스트 길이와 상자 크기를 변경합니다.그런 다음 크기를 수동으로 설정합니다.수동 결과를 좌표계에 표시합니다.그런 다음 여기에 올린 두 방정식을 입력하고 "내" 그래프가 수동으로 표시된 점에 맞을 때까지 숫자를 조정합니다.

콘텐츠 편집 테이블에 내 버전을 추가하고 싶을 뿐입니다.

$.fn.fitInText = function() {
  this.each(function() {

    let textbox = $(this);
    let textboxNode = this;

    let mutationCallback = function(mutationsList, observer) {
      if (observer) {
        observer.disconnect();
      }
      textbox.css('font-size', 0);
      let desiredHeight = textbox.css('height');
      for (i = 12; i < 50; i++) {
        textbox.css('font-size', i);
        if (textbox.css('height') > desiredHeight) {
          textbox.css('font-size', i - 1);
          break;
        }
      }

      var config = {
        attributes: true,
        childList: true,
        subtree: true,
        characterData: true
      };
      let newobserver = new MutationObserver(mutationCallback);
      newobserver.observe(textboxNode, config);

    };

    mutationCallback();

  });
}

$('#inner').fitInText();
#outer {
  display: table;
  width: 100%;
}

#inner {
  border: 1px solid black;
  height: 170px;
  text-align: center;
  display: table-cell;
  vertical-align: middle;
  word-break: break-all;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="outer">
  <div id="inner" contenteditable=true>
    TEST
  </div>
</div>

이것은 이진 검색을 사용하여 10회 반복합니다.간단한 방법은 요소가 오버플로우되기 시작할 때까지 잠시 루프하고 글꼴 크기를 1만큼 늘리는 것이었습니다.요소가 오버플로되기 시작하는 시기는 element.offset을 사용하여 결정할 수 있습니다.높이요소.스크롤 높이.스크롤 높이가 오프셋보다 큰 경우높이, 글꼴 크기가 너무 큽니다.

이진 검색이 훨씬 더 나은 알고리즘입니다.또한 수행할 반복 횟수에 따라 제한됩니다.flexFont를 호출하고 div를 삽입하기만 하면 8px에서 96px 사이의 글꼴 크기를 조정할 수 있습니다.

저는 이 주제를 연구하고 다른 도서관들을 시도하는 데 시간을 보냈지만, 궁극적으로 이것이 실제로 효과가 있을 가장 쉽고 간단한 해결책이라고 생각합니다.

▁use다▁to니▁note확합▁you인으로 변경할 수 .offsetWidth그리고.scrollWidth또는 둘 다 이 함수에 추가합니다.

    // Set the font size using overflow property and div height
    function flexFont(divId) {
        var content = document.getElementById(divId);
        content.style.fontSize = determineMaxFontSize(content, 8, 96, 10, 0) + "px";
    };

    // Use binary search to determine font size
    function determineMaxFontSize(content, min, max, iterations, lastSizeNotTooBig) {
        if (iterations === 0) {
            return lastSizeNotTooBig;
        }
        var obj = fontSizeTooBig(content, min, lastSizeNotTooBig);

        // if `min` too big {....min.....max.....}
        // search between (avg(min, lastSizeTooSmall)), min)
        // if `min` too small, search between (avg(min,max), max)
        // keep track of iterations, and the last font size that was not too big
        if (obj.tooBig) {
            (lastSizeTooSmall === -1) ?
                determineMaxFontSize(content, min / 2, min, iterations - 1, obj.lastSizeNotTooBig, lastSizeTooSmall) :
                    determineMaxFontSize(content, (min + lastSizeTooSmall) / 2, min, iterations - 1, obj.lastSizeNotTooBig, lastSizeTooSmall);
            
        } else {
            determineMaxFontSize(content, (min + max) / 2, max, iterations - 1, obj.lastSizeNotTooBig, min);
        }
    }

    // determine if fontSize is too big based on scrollHeight and offsetHeight, 
    // keep track of last value that did not overflow
    function fontSizeTooBig(content, fontSize, lastSizeNotTooBig) {
        content.style.fontSize = fontSize + "px";
        var tooBig = content.scrollHeight > content.offsetHeight;
        return {
            tooBig: tooBig,
            lastSizeNotTooBig: tooBig ? lastSizeNotTooBig : fontSize
        };
    }

저도 같은 문제가 발생했고, 기본적으로 자바스크립트를 사용하여 글꼴 크기를 제어하는 것이 해결책입니다.코드펜에서 다음 예를 확인합니다.

https://codepen.io/ThePostModernPlatonic/pen/BZKzVR

이 예는 높이에 대한 것입니다. 너비 정도라면 몇 개를 넣어야 할 수도 있습니다.

크기 조정을 시도합니다.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Documento sem título</title>
<style>
</style>
</head>
<body>
<div style="height:100vh;background-color: tomato;" id="wrap">        
  <h1 class="quote" id="quotee" style="padding-top: 56px">Because too much "light" doesn't <em>illuminate</em> our paths and warm us, it only blinds and burns us.</h1>
</div>
</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
  var multiplexador = 3;
  initial_div_height = document.getElementById ("wrap").scrollHeight;
  setInterval(function(){ 
    var div = document.getElementById ("wrap");
    var frase = document.getElementById ("quotee");
    var message = "WIDTH div " + div.scrollWidth + "px. "+ frase.scrollWidth+"px. frase \n";
    message += "HEIGHT div " + initial_div_height + "px. "+ frase.scrollHeight+"px. frase \n";           
    if (frase.scrollHeight < initial_div_height - 30){
      multiplexador += 1;
      $("#quotee").css("font-size", multiplexador); 
    }
    console.log(message);          
  }, 10);
</script>
</html>

좋아했습니다

let name = "Making statements based on opinion; back them up with references or personal experience."
let originFontSize = 15;
let maxDisplayCharInLine = 50; 
let fontSize = Math.min(originFontSize, originFontSize / (name.length / maxDisplayCharInLine));

루프를 사용하여 텍스트를 축소하는 것을 방지하는 방법을 찾았습니다.컨테이너 너비와 내용 너비 사이의 비율을 곱하여 글꼴 크기를 조정합니다.따라서 컨테이너의 너비가 내용의 1/3이면 글꼴 크기가 1/3로 줄어들고 컨테이너의 너비가 됩니다.스케일 업을 위해 콘텐츠가 컨테이너보다 클 때까지 잠시 루프를 사용했습니다.

function fitText(outputSelector){
    // max font size in pixels
    const maxFontSize = 50;
    // get the DOM output element by its selector
    let outputDiv = document.getElementById(outputSelector);
    // get element's width
    let width = outputDiv.clientWidth;
    // get content's width
    let contentWidth = outputDiv.scrollWidth;
    // get fontSize
    let fontSize = parseInt(window.getComputedStyle(outputDiv, null).getPropertyValue('font-size'),10);
    // if content's width is bigger than elements width - overflow
    if (contentWidth > width){
        fontSize = Math.ceil(fontSize * width/contentWidth,10);
        fontSize =  fontSize > maxFontSize  ? fontSize = maxFontSize  : fontSize - 1;
        outputDiv.style.fontSize = fontSize+'px';   
    }else{
        // content is smaller than width... let's resize in 1 px until it fits 
        while (contentWidth === width && fontSize < maxFontSize){
            fontSize = Math.ceil(fontSize) + 1;
            fontSize = fontSize > maxFontSize  ? fontSize = maxFontSize  : fontSize;
            outputDiv.style.fontSize = fontSize+'px';   
            // update widths
            width = outputDiv.clientWidth;
            contentWidth = outputDiv.scrollWidth;
            if (contentWidth > width){
                outputDiv.style.fontSize = fontSize-1+'px'; 
            }
        }
    }
}

이 코드는 Github https://github.com/ricardobrg/fitText/ 에 업로드한 테스트의 일부입니다.

저는 geekMonkey 솔루션으로 갔지만 너무 느립니다.그는 글꼴 크기를 최대(maxFontPixels)로 조정한 다음 컨테이너 내부에 맞는지 확인합니다.그렇지 않으면 글꼴 크기를 1인치 줄이고 다시 확인합니다.이전 컨테이너의 높이를 확인하고 그 값을 제출하는 것이 어떻습니까?(네, 이유는 압니다. 하지만 이제 높이에서만 작동하고 최소/최대 옵션도 있는 솔루션을 만들었습니다.)

여기 훨씬 더 빠른 솔루션이 있습니다.

var index_letters_resize;
(index_letters_resize = function() {
  $(".textfill").each(function() {
    var
      $this = $(this),
      height = Math.min( Math.max( parseInt( $this.height() ), 40 ), 150 );
    $this.find(".size-adjust").css({
      fontSize: height
    });
  });
}).call();

$(window).on('resize', function() {
  index_letters_resize();
);

그리고 이것은 HTML일 것입니다.

<div class="textfill">
  <span class="size-adjust">adjusted element</span>
  other variable stuff that defines the container size
</div>

다시 말하지만, 이 솔루션은 용기의 높이만 확인합니다.그렇기 때문에 이 기능은 요소가 내부에 맞는지 확인할 필요가 없습니다.그러나 최소/최대 값(40분, 150max)도 구현했으므로 이 작업은 완벽하게 수행됩니다(창 크기 조정에도 사용 가능).

이 솔루션의 다른 버전은 다음과 같습니다.

shrinkTextInElement : function(el, minFontSizePx) {
    if(!minFontSizePx) {
        minFontSizePx = 5;
    }
    while(el.offsetWidth > el.parentNode.offsetWidth || el.offsetHeight > el.parentNode.offsetHeight) {

        var newFontSize = (parseInt(el.style.fontSize, 10) - 3);
        if(newFontSize <= minFontSizePx) {
            break;
        }

        el.style.fontSize = newFontSize + "px";
    }
}

언급URL : https://stackoverflow.com/questions/687998/auto-size-dynamic-text-to-fill-fixed-size-container

반응형