我想使用JavaScript来计算字符串的宽度。如果不使用单行字体,这可能吗?
如果它不是内置的,我唯一的想法是为每个字符创建一个宽度表,但这是非常不合理的,特别是支持Unicode和不同的类型大小(以及所有浏览器)。
我想使用JavaScript来计算字符串的宽度。如果不使用单行字体,这可能吗?
如果它不是内置的,我唯一的想法是为每个字符创建一个宽度表,但这是非常不合理的,特别是支持Unicode和不同的类型大小(以及所有浏览器)。
当前回答
如果你可以安装一个包,并且你想要一个更权威或更精确的答案,你可以使用opentype.js(奇怪的是没有人提到这一点):
import { load } from "opentype.js";
const getWidth = async (text = "Hello World") => {
const font = await load("path/to/some/font");
const { x1, x2 } = font.getPath(text, 0, 0, 12).getBoundingBox();
return x2 - x1;
};
当然,您希望每个字体只调用load一次,因此应该根据您的情况将该行拉出到更高的范围。
下面是一个代码沙盒,将OpenType方法与Canvas和DOM方法进行比较: https://codesandbox.io/s/measure-width-of-text-in-javascript-vctst2
在我的机器上,每个100个样品,典型的结果是:
女士的OpenType: 5 女士帆布:3 女士DOM: 4
我发现的另一个软件包是:https://github.com/sffc/word-wrappr
其他回答
我使用文本度量包。工作真的很好,我尝试了这个解决方案,但在某些原因,它计算错误。
textMetrics.init(document.querySelector('h1'), { fontSize: '20px' });
textMetrics.init({
fontSize: '14px',
lineHeight: '20px',
fontFamily: 'Helvetica, Arial, sans-serif',
fontWeight: 400,
width: 100,
});
没有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);
ExtJS javascript库中有一个很棒的类,叫做Ext.util.TextMetrics,它“为文本块提供精确的像素测量,这样你就可以准确地确定给定文本块的高和宽(以像素为单位)”。您可以直接使用它,也可以查看它的源代码以了解如何完成此操作。
http://docs.sencha.com/extjs/6.5.3/modern/Ext.util.TextMetrics.html
根据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>
在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 (e.g. "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
const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
const context = canvas.getContext("2d");
context.font = font;
const metrics = context.measureText(text);
return metrics.width;
}
function getCssStyle(element, prop) {
return window.getComputedStyle(element, null).getPropertyValue(prop);
}
function getCanvasFont(el = document.body) {
const fontWeight = getCssStyle(el, 'font-weight') || 'normal';
const fontSize = getCssStyle(el, 'font-size') || '16px';
const fontFamily = getCssStyle(el, 'font-family') || 'Times New Roman';
return `${fontWeight} ${fontSize} ${fontFamily}`;
}
console.log(getTextWidth("hello there!", "bold 12pt arial")); // close to 86
如果你想使用特定元素myl的字体大小,你可以使用getCanvasFont实用函数:
const fontSize = getTextWidth(text, getCanvasFont(myEl));
// do something with fontSize here...
解释:getCanvasFontSize函数接受某些元素的字体(默认为正文),并将其转换为与上下文兼容的格式。字体属性。当然,任何元素在使用之前都必须首先添加到DOM中,否则会给您虚假的值。
更多的笔记
这种方法有几个优点,包括:
比其他(基于DOM的)方法更简洁和更安全,因为它不改变全局状态,比如DOM。 进一步的定制可以通过修改更多的画布文本属性,如textAlign和textBaseline。
注意:当你在DOM中添加文本时,记住还要考虑到填充、边距和边框。
注2:在某些浏览器上,该方法产生亚像素精度(结果是浮点数),在其他浏览器上则不是(结果只是一个int)。你可能想运行数学。floor(或Math.ceil),以避免不一致。由于基于dom的方法从来没有亚像素精度,因此该方法比这里的其他方法具有更高的精度。
根据这个jsperf(感谢评论中的贡献者),如果将缓存添加到基于dom的方法中,并且您没有使用Firefox,那么Canvas方法和基于dom的方法几乎一样快。在Firefox中,由于某种原因,这种Canvas方法要比基于dom的方法快得多(截至2014年9月)。
性能
本文将此Canvas方法与Bob Monteverde基于dom的方法的变体进行了比较,因此您可以分析和比较结果的准确性。