【问题标题】:Calculating text width计算文本宽度
【发布时间】:2010-12-07 15:22:11
【问题描述】:

我正在尝试使用 jQuery 计算文本宽度。我不确定是什么,但我肯定做错了什么。

所以,这里是代码:

var c = $('.calltoaction');

var cTxt = c.text();

var cWidth =  cTxt.outerWidth();

c.css('width' , cWidth);

【问题讨论】:

  • 那么,该代码以什么方式不起作用?它需要做些什么不同的事情?

标签: jquery


【解决方案1】:

这对我来说效果更好:

$.fn.textWidth = function(){
  var html_org = $(this).html();
  var html_calc = '<span>' + html_org + '</span>';
  $(this).html(html_calc);
  var width = $(this).find('span:first').width();
  $(this).html(html_org);
  return width;
};

【讨论】:

  • +1 - 这真正衡量了文本,而不仅仅是像 Brainreavis 的解决方案那样的包含块元素。
  • 光滑。 +1。看起来你在'&lt;/span&gt;' 之后的第三行缺少一个分号,尽管它似乎没有什么区别(在 FF9 上使用或不使用它)。
  • 请注意这一点...此方法将取消绑定子元素上的任何事件。
  • 我已经尝试以多种方式使用此函数,但它一直返回 null。有人可以发布这个函数实际使用的语法吗?我是否在 jQuery 对象上运行 .textWidth() 函数?我是否将文本传递给此函数?我是否将函数作为 jQuery 函数运行(即 $.textWidth(jqObject)?因为这些选项似乎都不起作用。谢谢...
  • @moosefetcher 你会这样做 $(selector).textWidth();看这里learn.jquery.com/plugins/basic-plugin-creation/…
【解决方案2】:

这是一个比其他人发布的更好的功能,因为

  1. 它更短
  2. 它在传递&lt;input&gt;&lt;span&gt;"string" 时有效。
  3. 频繁使用时速度更快,因为它重用了现有的 DOM 元素。

演示:http://jsfiddle.net/philfreo/MqM76/

// Calculate width of text from DOM element or string. By Phil Freo <http://philfreo.com>
$.fn.textWidth = function(text, font) {
    if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl = $('<span>').hide().appendTo(document.body);
    $.fn.textWidth.fakeEl.text(text || this.val() || this.text()).css('font', font || this.css('font'));
    return $.fn.textWidth.fakeEl.width();
};

【讨论】:

  • 哇!简直太棒了!
  • 很好的解决方案,我认为应该被接受!谢谢,朋友!
  • 太棒了!简单干净。
  • 虽然很好,但它不处理空格。请参阅@edsioufi 的答案以了解对此解决方案的增强。
  • 如果元素内有隐藏文本,那么它会扭曲你的宽度。考虑到这一点,请务必在计算文本宽度之前删除隐藏节点。为了安全地删除隐藏节点,您可能应该先进行克隆并在那里进行删除。
【解决方案3】:

My solution

$.fn.textWidth = function(){
    var self = $(this),
        children = self.children(),
        calculator = $('<span style="display: inline-block;" />'),
        width;

    children.wrap(calculator);
    width = children.parent().width(); // parent = the calculator wrapper
    children.unwrap();
    return width;
};

基本上是对 Rune 的改进,不会轻易使用.html

【讨论】:

  • Ajarn Gerhard 将其作为答案发布: 这在 IE8 中不起作用,因为您在 &lt;span&gt; 标记的右括号之前缺少 /calculator = $('&lt;span style="display: inline-block;" /&gt;'),
  • 如果您正在测量的元素下方有子元素,这似乎返回 null。它可以在没有子元素的情况下工作吗?见jsfiddle.net/h22tj/41
  • +1 - 我从来不知道有一个 unwrap(),这给我带来了无尽的悲伤。
  • 它在 Chrome 上总是返回 null。
【解决方案4】:

答案中提供的textWidth 函数接受string 作为参数将不考虑前导和尾随空格(那些不在虚拟容器中呈现)。此外,如果文本包含任何 html 标记,它们将不起作用(子字符串 &lt;br&gt; 不会产生任何输出,&amp;nbsp; 将返回一个空格的长度)。

这只是接受stringtextWidth 函数的问题,因为如果给定了一个DOM 元素,并且在该元素上调用了.html(),那么可能不需要为此修复此问题用例。

但是,例如,如果您正在计算文本的宽度以在用户键入时动态修改文本 input 元素的宽度(我当前的用例),您可能希望替换前导和尾随&amp;nbsp; 的空格并将字符串编码为 html。

我使用了 philfreo 的解决方案,所以这里有一个版本可以解决这个问题(添加了 cmets):

$.fn.textWidth = function(text, font) {
    if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl = $('<span>').appendTo(document.body);
    var htmlText = text || this.val() || this.text();
    htmlText = $.fn.textWidth.fakeEl.text(htmlText).html(); //encode to Html
    htmlText = htmlText.replace(/\s/g, "&nbsp;"); //replace trailing and leading spaces
    $.fn.textWidth.fakeEl.html(htmlText).css('font', font || this.css('font'));
    return $.fn.textWidth.fakeEl.width();
};

【讨论】:

  • 谢谢。您的回答最有价值。
  • 奇怪的是,当我尝试这个时,它没有正确复制font-size。我必须添加css('font-size'), this.css('font-size')) 才能正常工作。任何想法为什么单独 font 不会复制该值?
  • @GoneCoding 你在哪里添加了这些额外内容?
  • @webmagnets:与现有的.css 方法相同,但我看到我的括号是错误的。应该是css('font-size', this.css('font-size'))
【解决方案5】:

由于盒子模型不一致,当尝试确定文本宽度时,jQuery 的宽度函数可能会有些模糊。确定的方法是在元素中注入 div 以确定实际的文本宽度:

$.fn.textWidth = function(){
  var sensor = $('<div />').css({margin: 0, padding: 0});
  $(this).append(sensor);
  var width = sensor.width();
  sensor.remove();
  return width;
};

要使用这个迷你插件,只需:

$('.calltoaction').textWidth();

【讨论】:

  • 这不是给你块宽度而不是文本吗?
  • -1 这似乎确实测量了框的宽度而不是文本的宽度。
  • 不会简单地使用 span 代替 div 来解决宽度问题吗?如果是这样,那么这个函数比接受的答案要好一点。
  • @Josh:如果你用span 替换它,你只会得到零。在H2 上尝试了这个解决方案,其中父元素隐藏了溢出,我只得到了文本的截断长度。也许对它应该如何工作的解释有助于使其更好地工作?
【解决方案6】:

我发现这个解决方案效果很好,它在调整大小之前继承了原始字体:

$.fn.textWidth = function(text){
  var org = $(this)
  var html = $('<span style="postion:absolute;width:auto;left:-9999px">' + (text || org.html()) + '</span>');
  if (!text) {
    html.css("font-family", org.css("font-family"));
    html.css("font-size", org.css("font-size"));
  }
  $('body').append(html);
  var width = html.width();
  html.remove();
  return width;
}

【讨论】:

  • 我最终使用了这个,但添加了org.css("font-weight")。另外,我想说if(!text) 部分不直观。如果我使用例如jQuery("#someContainer").textWidth("Lorem ipsum") 我想知道在特定容器中应用“Lorem ipsum”的文本宽度。
【解决方案7】:

Rune 和 Brain 都不适合我,以防保存文本的元素具有固定宽度。我做了类似于 Okamera 的事情。它使用较少的选择器。

编辑: 它可能不适用于使用相对font-size 的元素,因为以下代码将htmlCalc 元素插入body 从而丢失了有关父关系的信息。

$.fn.textWidth = function() {
    var htmlCalc = $('<span>' + this.html() + '</span>');
    htmlCalc.css('font-size', this.css('font-size'))
            .hide()
            .prependTo('body');
    var width = htmlCalc.width();
    htmlCalc.remove();
    return width;
};

【讨论】:

  • 这对我来说是支持 IE8 的最佳解决方案,并且在此过程中不会破坏与元素的任何绑定!谢谢。
  • 注意:在 jQuery 扩展方法中,this 已经是一个 jQuery 对象,所以 $(this) 是多余的。
  • 这对我来说是错误的,因为计算的宽度太小了。接受的答案工作正常
【解决方案8】:

如果您尝试使用选择框中的文本执行此操作,或者如果这两个不起作用,请尝试使用这个:

$.fn.textWidth = function(){
 var calc = '<span style="display:none">' + $(this).text() + '</span>';
 $('body').append(calc);
 var width = $('body').find('span:last').width();
 $('body').find('span:last').remove();
 return width;
};

function textWidth(text){
 var calc = '<span style="display:none">' + text + '</span>';
 $('body').append(calc);
 var width = $('body').find('span:last').width();
 $('body').find('span:last').remove();
 return width;
};

如果你想先抓取文本

【讨论】:

    【解决方案9】:

    事情,你做错了,你在 cTxt 上调用一个方法,这是一个简单的字符串,而不是一个 jQuery 对象。 cTxt 是真正包含的文本。

    【讨论】:

      【解决方案10】:

      对 Nico 的稍作改动,因为如果我们引用 h1p 之类的文本元素,.children() 将返回一个空集。因此,我们将使用 .contents() 代替,并使用 this 代替 $(this),因为我们正在为 jQuery 对象创建一个方法。

      $.fn.textWidth = function(){
          var contents = this.contents(),
              wrapper  = '<span style="display: inline-block;" />',
              width    = '';
      
          contents.wrapAll(wrapper);
          width = contents.parent().width(); // parent is now the wrapper
          contents.unwrap();
          return width;
          };
      

      【讨论】:

        【解决方案11】:

        追了两天鬼,想弄清楚为什么一个文本的宽度不正确,我意识到这是因为文本字符串中的空格会停止宽度计算。

        所以,另一个提示是检查空格是否导致问题。使用

        &nbsp;
        

        非破坏空间,看看是否可以修复它。

        人们建议的其他功能也很好用,但是是空格造成了麻烦。

        【讨论】:

        • 只需将white-space: nowrap 临时添加到内联CSS 即可避免这种情况。
        【解决方案12】:

        如果您尝试确定给定元素内的文本节点和元素的混合宽度,您需要用wrapInner() 包裹所有内容,计算宽度,然后展开内容。

        *注意:您还需要扩展 jQuery 以添加 unwrapInner() 函数,因为默认情况下不提供它。

        $.fn.extend({
          unwrapInner: function(selector) {
              return this.each(function() {
                  var t = this,
                      c = $(t).children(selector);
                  if (c.length === 1) {
                      c.contents().appendTo(t);
                      c.remove();
                  }
              });
          },
          textWidth: function() {
            var self = $(this);
            $(this).wrapInner('<span id="text-width-calc"></span>');
            var width = $(this).find('#text-width-calc').width();
            $(this).unwrapInner();
            return width;
          }
        });
        

        【讨论】:

        • +1 表示 .wrapInner。您可能知道,在 jQuery 中处理纯文本元素是地狱。如果还有其他适用的 jQuery 方法,请告诉我。我不得不求助于 .get(0).children,但它并不漂亮。
        【解决方案13】:

        扩展@philfreo 的回答:

        我添加了检查text-transform 的功能,因为text-transform: uppercase 之类的内容通常会使文本变宽。

        $.fn.textWidth = function (text, font, transform) {
            if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl = $('<span>').hide().appendTo(document.body);
            $.fn.textWidth.fakeEl.text(text || this.val() || this.text())
                .css('font', font || this.css('font'))
                .css('text-transform', transform || this.css('text-transform'));
            return $.fn.textWidth.fakeEl.width();
        };
        

        【讨论】:

          【解决方案14】:
          var calc = '<span style="display:none; margin:0 0 0 -999px">' + $('.move').text() + '</span>';
          

          【讨论】:

            【解决方案15】:

            调用 getColumnWidth() 来获取文本的 with。这工作得很好。

            someFile.css
            .columnClass { 
                font-family: Verdana;
                font-size: 11px;
                font-weight: normal;
            }
            
            
            function getColumnWidth(columnClass,text) { 
                tempSpan = $('<span id="tempColumnWidth" class="'+columnClass+'" style="display:none">' + text + '</span>')
                      .appendTo($('body'));
                columnWidth = tempSpan.width();
                tempSpan.remove();
            return columnWidth;
            }
            

            注意:- 如果你想内联 .css 只传递样式中的字体细节。

            【讨论】:

              【解决方案16】:

              我修改了 Nico 的代码以满足我的需要。

              $.fn.textWidth = function(){
                  var self = $(this),
                      children = self.contents(),
                      calculator = $('<span style="white-space:nowrap;" />'),
                      width;
              
                  children.wrap(calculator);
                  width = children.parent().width(); // parent = the calculator wrapper
                  children.unwrap();
                  return width;
              };
              

              我正在使用.contents(),因为 .children() 不返回我需要的文本节点。我还发现返回的宽度受到导致换行的视口宽度的影响,所以我使用的是 white-space:nowrap;无论视口宽度如何,都能获得正确的宽度。

              【讨论】:

                【解决方案17】:
                $.fn.textWidth = function(){
                        var w = $('body').append($('<span stlye="display:none;" id="textWidth"/>')).find('#textWidth').html($(this).html()[0]).width();
                        $('#textWidth').remove();
                        console.log(w);
                        return w;
                    };
                

                几乎是一个班轮。 给你第一个字符的with

                【讨论】:

                  【解决方案18】:

                  我无法让列出的任何解决方案 100% 工作,所以想出了这个 hybrid,基于来自 @chmurson(又基于 @Okamera)和来自@philfreo:

                  (function ($)
                  {
                      var calc;
                      $.fn.textWidth = function ()
                      {
                          // Only create the dummy element once
                          calc = calc || $('<span>').css('font', this.css('font')).css({'font-size': this.css('font-size'), display: 'none', 'white-space': 'nowrap' }).appendTo('body');
                          var width = calc.html(this.html()).width();
                          // Empty out the content until next time - not needed, but cleaner
                          calc.empty();
                          return width;
                      };
                  })(jQuery);
                  

                  注意事项:

                  • jQuery 扩展方法中的this 已经是一个 jQuery 对象,因此不需要许多示例所具有的所有额外的$(this)
                  • 它只将虚拟元素添加到正文中一次,然后重复使用。
                  • 您还应该指定white-space: nowrap,以确保它将其测量为单行(而不是基于其他页面样式的换行)。
                  • 我无法单独使用font 使其工作,还必须明确复制font-size。尚不确定原因(仍在调查中)。
                  • @philfreo那样支持输入字段。

                  【讨论】:

                    【解决方案19】:

                    有时您还需要额外测量高度,不仅是文本,还需要测量HTML 宽度。我接受了@philfreo 的回答,使它更加灵活和有用:

                    function htmlDimensions(html, font) {
                      if (!htmlDimensions.dummyEl) {
                        htmlDimensions.dummyEl = $('<div>').hide().appendTo(document.body);
                      }
                      htmlDimensions.dummyEl.html(html).css('font', font);
                      return {
                        height: htmlDimensions.dummyEl.height(),
                        width: htmlDimensions.dummyEl.width()
                      };
                    }
                    

                    【讨论】:

                      【解决方案20】:

                      不同父母的文本宽度可能不同,例如,如果您将文本添加到 h1 标签中,它将比 div 或标签更宽,所以我的解决方案是这样的:

                      <h1 id="header1">
                      
                      </h1>
                      
                      alert(calcTextWidth("bir iki", $("#header1")));
                      
                      function calcTextWidth(text, parentElem){
                          var Elem = $("<label></label>").css("display", "none").text(text);
                          parentElem.append(Elem);
                        var width = Elem.width();
                        Elem.remove();
                          return width;
                      }
                      

                      【讨论】:

                        【解决方案21】:

                        我在使用 @rune-kaagaard 之类的大量文本解决方案时遇到了麻烦。我发现了这个:

                        $.fn.textWidth = function() {
                        	var width = 0;
                        	var calc = '<span style="display: block; width: 100%; overflow-y: scroll; white-space: nowrap;" class="textwidth"><span>' + $(this).html() + '</span></span>';
                        	$('body').append(calc);
                        	var last = $('body').find('span.textwidth:last');
                        	if (last) {
                        			var lastcontent = last.find('span');
                        			width = lastcontent.width();
                        			last.remove();
                        	}
                        	return width;
                        };

                        JSFiddle GitHub

                        【讨论】:

                          【解决方案22】:

                          如果该字段是定宽输入或contenteditable div,则可以获取水平滚动宽度为scrollWidth

                                $("input").on("input", function() {
                                  var width = el[0].scrollWidth;
                                  
                                  console.log(width);
                                });
                          

                          【讨论】:

                            猜你喜欢
                            • 2011-11-25
                            • 2010-09-12
                            • 2015-02-20
                            • 1970-01-01
                            • 2012-07-26
                            • 1970-01-01
                            • 2011-02-24
                            • 2011-03-18
                            相关资源
                            最近更新 更多