我想使用JavaScript来计算字符串的宽度。如果不使用单行字体,这可能吗?
如果它不是内置的,我唯一的想法是为每个字符创建一个宽度表,但这是非常不合理的,特别是支持Unicode和不同的类型大小(以及所有浏览器)。
我想使用JavaScript来计算字符串的宽度。如果不使用单行字体,这可能吗?
如果它不是内置的,我唯一的想法是为每个字符创建一个宽度表,但这是非常不合理的,特别是支持Unicode和不同的类型大小(以及所有浏览器)。
当前回答
getclientrects()方法返回一个DOMRect对象的集合,用于指示客户端中每个CSS边界框的包围矩形。返回值是一个DOMRect对象的集合,对应于与元素关联的每个CSS边框框。每个DOMRect对象都包含以像素为单位的描述边界框的只读左、上、右和下属性,其中左上角相对于视口的左上角。
Mozilla contributor的Element.getClientRects()是CC-BY-SA 2.5授权的。
将所有返回的矩形宽度相加,就得到了文本的总宽度(以像素为单位)。
document.getElementById('in').addEventListener('input', function (event) { var span = document.getElementById('text-render') span.innerText = event.target.value var rects = span.getClientRects() var widthSum = 0 for (var i = 0; i < rects.length; i++) { widthSum += rects[i].right - rects[i].left } document.getElementById('width-sum').value = widthSum }) <p><textarea id='in'></textarea></p> <p><span id='text-render'></span></p> <p>Sum of all widths: <output id='width-sum'>0</output>px</p>
其他回答
ExtJS javascript库中有一个很棒的类,叫做Ext.util.TextMetrics,它“为文本块提供精确的像素测量,这样你就可以准确地确定给定文本块的高和宽(以像素为单位)”。您可以直接使用它,也可以查看它的源代码以了解如何完成此操作。
http://docs.sencha.com/extjs/6.5.3/modern/Ext.util.TextMetrics.html
<span id="text">Text</span>
<script>
var textWidth = document.getElementById("text").offsetWidth;
</script>
只要<span>标记没有应用其他样式,这就可以工作。 offsetWidth将包括任何边框的宽度,水平填充,垂直滚动条宽度等。
我使用文本度量包。工作真的很好,我尝试了这个解决方案,但在某些原因,它计算错误。
textMetrics.init(document.querySelector('h1'), { fontSize: '20px' });
textMetrics.init({
fontSize: '14px',
lineHeight: '20px',
fontFamily: 'Helvetica, Arial, sans-serif',
fontWeight: 400,
width: 100,
});
对于任何一个在那里使用React和/或Typescript…
试试这个Codepen!
export default function App() {
const spanRef = useRef<HTMLSpanElement>(null);
const [textWidth, setTextWidth] = useState(0);
const getTextWidthInPixels = (ref: HTMLSpanElement) =>
ref.getBoundingClientRect().width;
useEffect(() => {
setTextWidth(getTextWidthInPixels(spanRef.current!));
}, [spanRef]);
return (
<div className="App">
<span
ref={spanRef}
contentEditable
suppressContentEditableWarning
onInput={() => setTextWidth(getTextWidthInPixels(spanRef.current!))}
>
Edit Me!!!
</span>
{`textWidth: ${textWidth}px`}
</div>
);
}
将文本包装在内联定位的元素(如<span>)中是个好主意。 useRef是React访问DOM元素的方式,在我们的例子中是<span> getBoundingClientRect可以获得任何DOM元素的总宽度。 contentteditable允许用户更改元素的内容…这有点不安全(React会抛出警告!) suppresscontentteditablewarning将帮助我们防止这些警告
下面的代码片段,“计算”span标签的宽度,如果它太长,就添加“…”,并减少文本长度,直到它适合它的父标签(或者直到它尝试了超过1000次)
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)
}
}
});