我本想喜欢那个被接受的答案,但基本上符合我的标准的答案都需要使用一个库。与其熟悉另一个库,然后弄清楚如何使用它并准备调试它(如果它不起作用),我决定编写一个简单的函数,这个函数对我来说完美地工作。
理论:
- 传入您需要适配的字符串
- 传入您将从中继承文本样式的父级
- 可选地传入自定义属性(例如,您将从中继承字体和其他属性的类/ID,或仅自定义内联样式)
- 函数将在屏幕外创建一个具有该文本、父级和这些属性的文本元素,字体大小为1px,并测量它
- 然后,在循环中,它将逐像素增加字体大小,直到超过宽度限制;一旦完成,它将返回最后一个适合的字体大小
- 然后,它删除测试元素
- 当然,所有这些都发生得非常快
限制:
- 我不关心动态屏幕调整大小,因为这与我的上下文无关。我只关心在生成文本时运行时的屏幕大小。
- 我依赖于一个小型辅助函数,我还在代码中其他地方使用它,它基本上存在于 mithril.js 的一个函数版本中;老实说,我在几乎每个项目中都使用这个小函数,它值得学习。
function findMaxFontSize(
string="a string",
parent=document.body,
attributes={id:'font-size-finder',class:'some-class-with-font'}
) {
attributes.style = 'position:absolute; left:-10000; font-size:1px;' + (attributes.style || "");
let testFontEl = createEl('p', attributes, string);
parent.appendChild(testFontEl);
let currentWidth = testFontEl.offsetWidth;
let workingFontSize = 1;
let i = 0;
while (currentWidth < maxWidth && i < 1000) {
testFontEl.style.fontSize = Number(testFontEl.style.fontSize.split("px")[0]) + 1 + "px";
currentWidth = testFontEl.offsetWidth;
if (currentWidth < maxWidth) {
workingFontSize = testFontEl.style.fontSize;
}
i++;
}
console.log("determined maximum font size:",workingFontSize,'one larger would produce',currentWidth,'max width allowed is',maxWidth,'parent is',parent);
parent.removeChild(testFontEl);
return workingFontSize.split("px")[0];
}
function createEl(tag="div", attrs={class:'some-class'}, children=[]) {
let el = document.createElement(tag);
if (attrs) {
Object.keys(attrs).forEach(attr => {
el.setAttribute(attr, attrs[attr])
})
}
if (children) {
children = Array.isArray(children) ? children : [children];
for (let child of children) {
if (typeof child === "number") child = ""+child;
if (typeof child === "string") {
el.insertAdjacentText("afterbegin", child);
}
else {
try {
el.appendChild(child)
} catch (e) {
debugger
}
}
}
}
return el;
};
使用:
const getUsername = () => "MrHarry";
const username = getUsername();
const anchor = document.querySelector('.container');
const titleFontSize = findMaxFontSize(`Welcome, ${username}`, anchor, {style:'font-weight:900;'});
const titleFontStyle = `font-size:${titleFontSize}px;`;