我需要显示用户输入的文本到一个固定大小的div。我想要的是字体大小自动调整,以便文本尽可能多地填充框。

如果div是400px x 300px。如果有人输入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>

其他回答

编辑:此代码用于在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);

您可能需要将这些数字从font-family调整为font-family。一个很好的方法就是下载一个叫做GeoGebra的免费图形可视化工具。更改文本的长度和框的大小。然后手动设置大小。将手工结果绘制到坐标系统中。然后输入我在这里发布的两个方程,然后调整数字,直到“我的”图形符合你自己手动绘制的点。

下面是接受的答案的一个版本,它也可以接受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);

我没有发现任何以前的解决方案是足够的,由于糟糕的性能,所以我自己使用简单的数学,而不是循环。在所有浏览器中都可以正常工作。

根据这个性能测试用例,它比这里找到的其他解决方案快得多。

(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。

它使用二分搜索,进行10次迭代。最简单的方法是执行while循环,并将字体大小增加1,直到元素开始溢出。可以使用element来确定元素何时开始溢出。offsetHeight和element.scrollHeight。如果scrollHeight大于offsetHeight,则字体大小过大。

二分搜索是一个更好的算法。它还受到希望执行的迭代次数的限制。只需调用flexFont并插入div id,它将在8px到96px之间调整字体大小。

我花了一些时间研究这个主题,并尝试了不同的库,但最终我认为这是最简单、最直接的解决方案。

注意,如果你愿意,你可以更改使用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
        };
    }

下面是一种改进的循环方法,它使用二进制搜索在尽可能少的步骤中找到适合父字体的最大可能大小(这比按固定字体大小步进更快更准确)。代码还在几个方面进行了性能优化。

默认情况下,将执行10个二进制搜索步骤,这将在最佳大小的0.1%之内。相反,您可以将numIter设置为某个值N,以获得最佳大小的1/2^N范围内。

用CSS选择器调用它,例如:fittopparent ('.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);
        }
    });
};