Javascript jQuery脚本效率

Javascript jQuery脚本效率,javascript,jquery,performance,Javascript,Jquery,Performance,我在数百个div上使用下面名为textfill的jQuery函数。基本上,它调整内部文本的大小以适应封闭的div,这样文本的字体大小是最大的,因此较长的文本比较短的文本小,但处于最大字体大小,这样它们就不会从div溢出 ; (function($) { /** * Resizes an inner element's font so that the inner element completely fills the outer element. * @version

我在数百个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);
它需要40到70秒,这取决于div的数量。我迫切需要调整代码,使其运行得更快。我已经试了两个小时了,但似乎无法让它跑得更快。有人能帮忙吗

编辑:

从注释中获取一些输入,并将代码更改为:

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

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

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

为什么不使用“二等分”来确定字体大小

对于200个div:


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

当前解决方案


最重要的代码:

        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;
var change=Math.ceil(fontSize/2);
while(true){
变更=数学单元(变更/2);
var-prev=fontSize;
做{
fontSize=fontSize-更改;
css('font-size',fontSize);
textHeight=ourText.height();
textWidth=ourText.width();
}而((textHeight>maxHeight | | textWidth>maxWidth)&&fontSize>3);
变更=数学单元(变更/2);
while(textHeight
$('.textDiv').each(function(){$(this).textfill({maxFontPixels:28}))

你用错函数了。每个(适当的)插件都已经在jQuery集合上工作,并且内置了
每个
,这样您就不需要在调用时使用它了。照办

$('.textDiv').textfill({ maxFontPixels: 28 });
但我认为这不是你真正的问题;循环速度相当快,即使是一百个项目,也不需要几秒钟。问题是

            ourText.css('font-size', fontSize);
            textHeight = ourText.height();
            textWidth = ourText.width();
在一个循环内(实际上是两个嵌套循环),因为它需要浏览器完全回流。您需要最小化对此部分的调用,例如,通过使用某种二进制搜索()和/或通过应用近似字体大小的度量(例如,字符数除以面积?)来获得良好的起始值

除此之外,还有其他一些小优化:

  • 缓存
    $(此)
  • $(Opts.innerTag+':visible:first',this)看起来像一个非常复杂的选择器。这真的有必要吗?你希望隐藏元素吗?将这些附加项移动到选项中,并默认使用
    $(this).children().first()
  • 我不确定您的CSS,但是如何设置div的尺寸(您检索为
    maxHeight
    /
    maxWidth
    )?为了在更改内部fontsize时降低回流成本,额外的
    overflow:hidden
    会有所帮助

您正在尝试的是一种昂贵的操作。但我记得有一次读到(对不起,没有消息来源)“each”函数效率很低。你试过使用普通的javascript for循环吗?我试过的另一件事是做
$('.textDiv').textfill({maxFontPixels:28})
但我认为这是对每个
Tom的隐式调用,您评论中的示例将更有效。在
textfill()
插件中,它是对
.each()
的显式调用,而不管您传入了什么jQuery对象,但是注释中的方式避免了在插件中重复设置默认值。插件中的
.each()
可以按照鲁本的建议,通过转换成标准的
for
循环来加速
$(Opts.innerTag,this).filter(“:visible”).first()
可能比直接使用
:visible
选择器更快。如果您可以省略
:visible
部分,该部分也会更快。我怀疑真正缓慢的部分是内部循环中的所有调整。@nnnnnn使用了您的两个建议,但没有显著的改进
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;
$('.textDiv').textfill({ maxFontPixels: 28 });
            ourText.css('font-size', fontSize);
            textHeight = ourText.height();
            textWidth = ourText.width();