고정 크기 컨테이너를 채울 수있는 동적 크기 자동 텍스트 고정 크기

사용자가 입력 한 텍스트를 고정 크기 div로 표시해야합니다. 내가 원하는 것은 텍스트가 가능한 한 상자를 채우도록 글꼴 크기를 자동으로 조정하는 것입니다.

따라서-div가 400px x 300px 인 경우. 누군가가 ABC를 입력하면 정말 큰 글꼴입니다. 문단을 입력하면 작은 글꼴이됩니다.

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



답변

감사 공격 . jQuery를 사용하고 싶었습니다.

당신은 나를 올바른 방향으로 지적했고, 이것이 내가 끝낸 것입니다.

다음은 플러그인에 대한 링크입니다 : 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>

이것은 첫 번째 jquery 플러그인이므로 아마도 좋지 않을 것입니다. 포인터는 확실히 환영합니다.


답변

이전 솔루션 중 성능이 좋지 않아 충분히 적합한 솔루션을 찾지 못했기 때문에 루핑 대신 간단한 수학을 사용하는 솔루션을 만들었습니다. 모든 브라우저에서도 잘 작동합니다.

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

(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의 높이와 너비는 고정되어 있어야하며 여러 줄로 텍스트 줄 바꿈을 지원하지 않습니다.

최대 글꼴 크기를 설정하는 옵션을 얻는 중입니다.

편집 : 플러그인에 더 많은 문제가 있음을 발견했습니다. 표준 모델 이외의 다른 상자 모델을 처리하지 않으며 div에 여백이나 테두리를 가질 수 없습니다. 나는 그것을 할 것입니다.

Edit2 : 나는 이제 이러한 문제와 한계를 수정하고 더 많은 옵션을 추가했습니다. 최대 글꼴 크기를 설정할 수 있으며 너비, 높이 또는 둘 다를 사용하여 글꼴 크기를 제한하도록 선택할 수도 있습니다. 래퍼 요소에서 최대 너비 및 최대 높이 값을 허용하도록 노력하겠습니다.

Edit3 : 플러그인을 버전 1.2.0으로 업데이트했습니다. 코드 및 새로운 옵션 (verticalAlign, horizontalAlign, textAlign)에 대한 주요 정리 및 span 태그 내부의 내부 요소 지원 (줄 바꿈 또는 멋진 아이콘)


답변

이것은 GeekyMonkey가 위에 게시 한 내용을 기반으로하며 약간 수정되었습니다.

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


답변

AngularJS에 대한 지시문을 만들었습니다 .GeekyMonkey의 답변에서 영감을 얻었지만 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();
      });
    }
  };
});