2

我使用以下textfill在数百个 div 上命名的 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 })});  

根据 div 的数量,需要 40 到 70 秒。我迫切需要调整代码以使其运行得更快。我已经尝试了过去两个小时,但似乎无法让它运行得更快。有人可以帮忙吗?

编辑:

从评论中获取一些输入并将代码更改为:

var items = document.getElementsByClassName("textDiv");
for (var i = items.length; i--;) {
    $(items[i]).textfill({ maxFontPixels: 28 });
}

它似乎有点快,但仍然很慢。

4

2 回答 2

1

$('.textDiv').each(function() { $(this).textfill({ maxFontPixels: 28 })});

您使用的功能错误。每个(适当的)插件都已经在 jQuery 集合上工作,并且具有each内置的,因此您不需要将它放在调用周围。做就是了

$('.textDiv').textfill({ maxFontPixels: 28 });

然而我认为这不是你的实际问题。循环非常快,即使是一百个项目也不需要几秒钟。问题是

            ourText.css('font-size', fontSize);
            textHeight = ourText.height();
            textWidth = ourText.width();

在一个循环中(实际上是在两个嵌套循环中),因为它需要浏览器进行完整的重排。您将需要最小化对这部分的调用,例如通过使用某种二进制搜索 ( bisection ) 和/或通过应用近似字体大小的插值度量(例如,字符数除以区域?)以获得良好的起始值。

除此之外,可能还有其他小的优化:

  • 缓存$(this)
  • $(Opts.innerTag + ':visible:first', this);看起来像一个相当复杂的选择器。这真的有必要吗,你期待隐藏的元素吗?将这些附加功能移到选项中,并$(this).children().first()默认使用。
  • 我不确定您的 CSS,但是您如何设置 div 的尺寸(您检索为maxHeight/ maxWidth)?为了在更改内部字体大小时降低回流成本,额外的overflow:hidden可以提供帮助。
于 2013-04-06T12:44:57.770 回答
0

显然瓶颈是最内层的循环(下一个是最内层的父级,依此类推)。

为什么不使用“二等分”来找出字体大小?:

对于 200 个 div:


二等分解决方案(需要一些重构):

http://jsfiddle.net/nx2n2/8/

Time: ~700

当前解决方案

http://jsfiddle.net/pXL5z/3/

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;
于 2013-04-06T12:38:48.473 回答