我需要显示用户输入的文本到一个固定大小的div。我想要的是字体大小自动调整,以便文本尽可能多地填充框。
如果div是400px x 300px。如果有人输入ABC,那么字体就很大。如果他们输入一个段落,那么它将是一个很小的字体。
我可能想要从最大字体大小开始——可能是32px,当文本太大而不适合容器时,缩小字体大小直到它适合。
我需要显示用户输入的文本到一个固定大小的div。我想要的是字体大小自动调整,以便文本尽可能多地填充框。
如果div是400px x 300px。如果有人输入ABC,那么字体就很大。如果他们输入一个段落,那么它将是一个很小的字体。
我可能想要从最大字体大小开始——可能是32px,当文本太大而不适合容器时,缩小字体大小直到它适合。
当前回答
我用geekMonkey解决方案,但它太慢了。他所做的就是将字体大小调整到最大(maxFontPixels),然后检查它是否适合容器。否则,它将字体大小减小1px,并再次检查。为什么不简单地检查前一个容器的高度并提交该值呢?(是的,我知道为什么,但我现在做了一个解决方案,这只适用于高度,也有一个最小/最大选项)
这里有一个更快的解决方案:
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>
同样,这个解决方案只检查容器的高度。这就是为什么这个函数不需要检查元素是否在里面。但我也实现了一个最小/最大值(40min, 150max),所以对我来说,这是完美的(也适用于窗口大小调整)。
其他回答
我用geekMonkey解决方案,但它太慢了。他所做的就是将字体大小调整到最大(maxFontPixels),然后检查它是否适合容器。否则,它将字体大小减小1px,并再次检查。为什么不简单地检查前一个容器的高度并提交该值呢?(是的,我知道为什么,但我现在做了一个解决方案,这只适用于高度,也有一个最小/最大选项)
这里有一个更快的解决方案:
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>
同样,这个解决方案只检查容器的高度。这就是为什么这个函数不需要检查元素是否在里面。但我也实现了一个最小/最大值(40min, 150max),所以对我来说,这是完美的(也适用于窗口大小调整)。
我没有发现任何以前的解决方案是足够的,由于糟糕的性能,所以我自己使用简单的数学,而不是循环。在所有浏览器中都可以正常工作。
根据这个性能测试用例,它比这里找到的其他解决方案快得多。
(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。
下面是接受的答案的一个版本,它也可以接受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);
它使用二分搜索,进行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
};
}
所提出的迭代解决方案可以在两个方面显著加速:
1)将字体大小乘以某个常数,而不是加或减1。
2)首先,使用零过程常数,比如,将每个循环的大小增加一倍。然后,有了一个大致的想法从哪里开始,做同样的事情,并进行更精细的调整,比如乘以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');