我在数百个div上使用下面名为textfill
的jQuery函数。基本上它调整内部文本的大小以适应封闭的div,使文本的字体大小最大,因此较长的文本比较短的文本小,但是它们的最大字体大小可以不受div的溢出。
; (function($) {
/**
* Resizes an inner element's font so that the inner element completely fills the outer element.
* @version 0.1
* @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,
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 > 3);
var pos = (maxHeight-textHeight)/2;
ourText.css('top', pos +'px');
});
};
})(jQuery);
因为我在数百个div上运行此脚本,如下所示:
<div class="textDiv"><span>text appears here</span></div>
同时使用:
$('.textDiv').each(function() { $(this).textfill({ maxFontPixels: 28 })});
需要40到70秒,具体取决于div的数量。我迫切需要调整代码,以便它运行得更快。我已经尝试了最后两个小时,但似乎无法让它跑得更快。有人可以帮忙吗?
修改
从评论中获取一些输入并将代码更改为:
var items = document.getElementsByClassName("textDiv");
for (var i = items.length; i--;) {
$(items[i]).textfill({ maxFontPixels: 28 });
}
似乎有点快,但仍然很慢。
答案 0 :(得分:1)
$('.textDiv').each(function() { $(this).textfill({ maxFontPixels: 28 })});
您使用的功能错误。每个(适当的)插件都可以在jQuery集合上运行,并且内置each
,因此您无需将其置于调用之外。只是做
$('.textDiv').textfill({ maxFontPixels: 28 });
但我认为这不是你的实际问题;循环非常快,即使是100件物品也不会花费几秒钟。问题是
ourText.css('font-size', fontSize);
textHeight = ourText.height();
textWidth = ourText.width();
在循环内部(实际上在两个嵌套循环中),因为它需要浏览器完全重排。您需要最小化对此部分的调用,例如使用某种二进制搜索(bisection)和/或应用近似字体大小的interpolation指标(字符数除以例如?)以获得良好的起始价值。
除此之外,可能还有其他一些小的优化:
$(this)
$(Opts.innerTag + ':visible:first', this);
看起来像一个非常复杂的选择器。这真的是必要的,你期待隐藏的元素吗?将此类额外内容移至选项,默认情况下使用$(this).children().first()
。maxHeight
/ maxWidth
)?为了在更改内部字体大小时降低回流成本,额外的overflow:hidden
可以提供帮助。答案 1 :(得分:0)
显然瓶颈是最里面的循环(下一个是最内层的父亲,依此类推)。
为什么不使用“bisection”来查找字体大小?:
200个div:
Bisect解决方案(需要一些重构):
Time: ~700
当前解决方案:
Time: ~1400
最重要的代码:
var change = Math.ceil(fontSize / 2);
while(true) {
change = Math.ceil(change / 2);
var prev = fontSize;
do {
fontSize = fontSize - change;
ourText.css('font-size', fontSize);
textHeight = ourText.height();
textWidth = ourText.width();
} while ((textHeight > maxHeight || textWidth > maxWidth) && fontSize > 3);
change = Math.ceil(change / 2);
while (textHeight < maxHeight && textWidth < maxWidth) {
fontSize = fontSize + change;
ourText.css('font-size', fontSize);
textHeight = ourText.height();
textWidth = ourText.width();
}
var current = fontSize;
if(prev == current) {
break;
}
}
// this is because you subtract after change in your original solution
// only for 'compatibility' with original solution
fontSize = fontSize - 1;