使用JavaScript计算文字宽度

我想使用JavaScript来计算string的宽度。 这是可能的,而不必使用等宽字体?

如果它不是内置的,我唯一的想法是为每个字符创build一个宽度表,但是这是非常不合理的,特别是支持Unicode和不同types的大小(以及所有的浏览器)。

使用以下样式创build一个DIV风格。 在JavaScript中,设置您要测量的字体大小和属性,将string放在DIV中,然后读取DIV的当前宽度和高度。 它将伸展以适应内容,并且大小将在string呈现大小的几个像素内。

HTML:

 <div id="Test"> abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ </div> 

CSS:

 #Test { position: absolute; visibility: hidden; height: auto; width: auto; white-space: nowrap; /* Thanks to Herb Caudill comment */ } 

JavaScript(片段):

 var test = document.getElementById("Test"); test.style.fontSize = fontSize; var height = (test.clientHeight + 1) + "px"; var width = (test.clientWidth + 1) + "px"; 

HTML 5中 ,您可以使用Canvas.measureText方法 ( 这里进一步解释)。

试试这个小提琴 :

 /** * Uses canvas.measureText to compute and return the width of the given text of given font in pixels. * * @param {String} text The text to be rendered. * @param {String} font The css font descriptor that text is to be rendered with (eg "bold 14px verdana"). * * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393 */ function getTextWidth(text, font) { // re-use canvas object for better performance var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas")); var context = canvas.getContext("2d"); context.font = font; var metrics = context.measureText(text); return metrics.width; } console.log(getTextWidth("hello there!", "bold 12pt arial")); // close to 86 

这个小提琴将这个Canvas方法与Bob Monteverde的基于DOM的方法的变体进行比较,因此您可以分析和比较结果的准确性。

这种方法有几个优点,包括:

  • 比其他基于DOM的方法更简洁,更安全,因为它不会改变全局状态,比如你的DOM。
  • 通过修改更多的canvas文本属性 ,例如textAligntextBaseline ,可以进一步自定义。

注意:将文本添加到DOM时,请记住也要考虑填充,边距和边框 。

注2:在某些浏览器上,这种方法产生子像素精度(结果是一个浮点数),而在其他浏览器上则不然(结果只是一个整数)。 您可能想要在结果上运行Math.floor (并可能加1)以避免不一致。 由于基于DOM的方法从来不是子像素精确的,所以这种方法比其他方法具有更高的精度。

根据这个jsperf (感谢贡献者的注释),如果将caching添加到基于DOM的方法中,并且您没有使用Firefox,则Canvas方法基于DOM的方法速度相当快。 在Firefox中,出于某种原因,这种Canvas方法基于DOM的方法要快得多(截至2014年9月)。

这是一个我没有例子一起鞭打。 看起来我们都在同一页面上。

 String.prototype.width = function(font) { var f = font || '12px arial', o = $('<div>' + this + '</div>') .css({'position': 'absolute', 'float': 'left', 'white-space': 'nowrap', 'visibility': 'hidden', 'font': f}) .appendTo($('body')), w = o.width(); o.remove(); return w; } 

使用它很简单: "a string".width()

**添加了white-space: nowrap因此可以计算宽度大于窗口宽度的string。

jQuery的:

 (function($) { $.textMetrics = function(el) { var h = 0, w = 0; var div = document.createElement('div'); document.body.appendChild(div); $(div).css({ position: 'absolute', left: -1000, top: -1000, display: 'none' }); $(div).html($(el).html()); var styles = ['font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing']; $(styles).each(function() { var s = this.toString(); $(div).css(s, $(el).css(s)); }); h = $(div).outerHeight(); w = $(div).outerWidth(); $(div).remove(); var ret = { height: h, width: w }; return ret; } })(jQuery); 

这适用于我…

 // Handy JavaScript to meature the size taken to render the supplied text; // you can supply additional style information too if you have it. function measureText(pText, pFontSize, pStyle) { var lDiv = document.createElement('div'); document.body.appendChild(lDiv); if (pStyle != null) { lDiv.style = pStyle; } lDiv.style.fontSize = "" + pFontSize + "px"; lDiv.style.position = "absolute"; lDiv.style.left = -1000; lDiv.style.top = -1000; lDiv.innerHTML = pText; var lResult = { width: lDiv.clientWidth, height: lDiv.clientHeight }; document.body.removeChild(lDiv); lDiv = null; return lResult; } 

ExtJS JavaScript库有一个很好的类叫做Ext.util.TextMetrics,它可以为文本块提供精确的像素测量,从而确定给定的文本块的像素高度和宽度。 您可以直接使用它或查看源代码来查看如何完成。

http://extjs.com/deploy/dev/docs/?class=Ext.util.TextMetrics

我为此写了一个小工具。 也许这对某个人有用。 它没有jQuery的工作

https://github.com/schickling/calculate-size

用法:

 var size = calculateSize("Hello world!", { font: 'Arial', fontSize: '12px' }); console.log(size.width); // 65 console.log(size.height); // 14 

小提琴: http : //jsfiddle.net/PEvL8/

你可以使用canvas,所以你不必处理这么多的CSS属性:

 var canvas = document.createElement("canvas"); var ctx = canvas.getContext("2d"); ctx.font = "20pt Arial"; // This can be set programmaticly from the element's font-style if desired var textWidth = ctx.measureText($("#myElement").text()).width; 
 <span id="text">Text</span> <script> var textWidth = document.getElementById("text").offsetWidth; </script> 

只要<span>标签没有应用其他样式,这应该工作。 offsetWidth将包含任何边框的宽度,水平填充,垂直滚动条宽度等。

在下面的代码片段中,“计算”span标签的宽度,如果它太长并且减less了文本长度,那么会附加“…”,直到它适合于它的父亲(或者直到它已经尝试了超过一千次)

CSS

 div.places { width : 100px; } div.places span { white-space:nowrap; overflow:hidden; } 

HTML

 <div class="places"> <span>This is my house</span> </div> <div class="places"> <span>And my house are your house</span> </div> <div class="places"> <span>This placename is most certainly too wide to fit</span> </div> 

JavaScript(使用jQuery)

 // loops elements classed "places" and checks if their child "span" is too long to fit $(".places").each(function (index, item) { var obj = $(item).find("span"); if (obj.length) { var placename = $(obj).text(); if ($(obj).width() > $(item).width() && placename.trim().length > 0) { var limit = 0; do { limit++; placename = placename.substring(0, placename.length - 1); $(obj).text(placename + "..."); } while ($(obj).width() > $(item).width() && limit < 1000) } } }); 

试试这个代码:

 function GetTextRectToPixels(obj) { var tmpRect = obj.getBoundingClientRect(); obj.style.width = "auto"; obj.style.height = "auto"; var Ret = obj.getBoundingClientRect(); obj.style.width = (tmpRect.right - tmpRect.left).toString() + "px"; obj.style.height = (tmpRect.bottom - tmpRect.top).toString() + "px"; return Ret; } 

文本的宽度和高度可以通过clientWidthclientHeight获得

 var element = document.getElementById ("mytext"); var width = element.clientWidth; var height = element.clientHeight; 

确保样式位置属性设置为绝对

 element.style.position = "absolute"; 

不需要在一个div ,可以在一个pspan

更好的方法是在显示元素之前检测文本是否适合。 所以你可以使用这个不需要元素在屏幕上的function。

 function textWidth(text, fontProp) { var tag = document.createElement("div"); tag.style.position = "absolute"; tag.style.left = "-999em"; tag.style.whiteSpace = "nowrap"; tag.style.font = fontProp; tag.innerHTML = text; document.body.appendChild(tag); var result = tag.clientWidth; document.body.removeChild(tag); return result; } 

用法:

 if ( textWidth("Text", "bold 13px Verdana") > elementWidth) { ... } 

小提琴的工作例子: http : //jsfiddle.net/tdpLdqpo/1/

HTML:

 <h1 id="test1"> How wide is this text? </h1> <div id="result1"></div> <hr/> <p id="test2"> How wide is this text? </p> <div id="result2"></div> <hr/> <p id="test3"> How wide is this text?<br/><br/> f sdfj f sdlfj lfj lsdk jflsjd fljsd flj sflj sldfj lsdfjlsdjkf sfjoifoewj flsdjfl jofjlgjdlsfjsdofjisdojfsdmfnnfoisjfoi ojfo dsjfo jdsofjsodnfo sjfoj ifjjfoewj fofew jfos fojo foew jofj sfj </p> <div id="result3"></div> 

JavaScript代码:

 function getTextWidth(text, font) { var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas")); var context = canvas.getContext("2d"); context.font = font; var metrics = context.measureText(text); return metrics.width; }; $("#result1") .text("answer: " + getTextWidth( $("#test1").text(), $("#test1").css("font")) + " px"); $("#result2") .text("answer: " + getTextWidth( $("#test2").text(), $("#test2").css("font")) + " px"); $("#result3") .text("answer: " + getTextWidth( $("#test3").text(), $("#test3").css("font")) + " px"); 

基于Deepak Nadar的回答 ,我改变了函数的参数来接受文本和字体样式。 你不需要引用一个元素。 此外, fontOptions有默认值,所以你不需要提供所有的。

 (function($) { $.format = function(format) { return (function(format, args) { return format.replace(/{(\d+)}/g, function(val, pos) { return typeof args[pos] !== 'undefined' ? args[pos] : val; }); }(format, [].slice.call(arguments, 1))); }; $.measureText = function(html, fontOptions) { fontOptions = $.extend({ fontSize: '1em', fontStyle: 'normal', fontWeight: 'normal', fontFamily: 'arial' }, fontOptions); var $el = $('<div>', { html: html, css: { position: 'absolute', left: -1000, top: -1000, display: 'none' } }).appendTo('body'); $(fontOptions).each(function(index, option) { $el.css(option, fontOptions[option]); }); var h = $el.outerHeight(), w = $el.outerWidth(); $el.remove(); return { height: h, width: w }; }; }(jQuery)); var dimensions = $.measureText("Hello World!", { fontWeight: 'bold', fontFamily: 'arial' }); // Font Dimensions: 94px x 18px $('body').append('<p>').text($.format('Font Dimensions: {0}px x {1}px', dimensions.width, dimensions.height)); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 

我猜这是与Depak入门类似,但是基于Louis Lazaris在印象深刻的网页上发表的一篇文章

 (function($){ $.fn.autofit = function() { var hiddenDiv = $(document.createElement('div')), content = null; hiddenDiv.css('display','none'); $('body').append(hiddenDiv); $(this).bind('fit keyup keydown blur update focus',function () { content = $(this).val(); content = content.replace(/\n/g, '<br>'); hiddenDiv.html(content); $(this).css('width', hiddenDiv.width()); }); return this; }; })(jQuery); 

在函数关联到控件后,fit事件用于执行函数调用。

例如:$('input')。autofit()。trigger(“fit”);

没有jQuery:

 String.prototype.width = function (fontSize) { var el, f = fontSize + " px arial" || '12px arial'; el = document.createElement('div'); el.style.position = 'absolute'; el.style.float = "left"; el.style.whiteSpace = 'nowrap'; el.style.visibility = 'hidden'; el.style.font = f; el.innerHTML = this; el = document.body.appendChild(el); w = el.offsetWidth; el.parentNode.removeChild(el); return w; } // Usage "MyString".width(12); 
 var textWidth = (function (el) { el.style.position = 'absolute'; el.style.top = '-1000px'; document.body.appendChild(el); return function (text) { el.innerHTML = text; return el.clientWidth; }; })(document.createElement('div'));