获取在浏览器中渲染的准确字体,可以使用浏览器扩展。

6
我知道你可以通过 window.getComputedStyle() 获取 font-family 值,但这并不总是浏览器用来渲染的确切字体。例如,如果给定的文本包含字体家族不支持的多语言文本,则浏览器会部分使用系统字体来呈现文本。
如果你查看 Chrome 或 Firefox 内置的 Web 开发工具,它们都有一个小区域来显示精确使用的字体(在 Chrome 上为 Rendered Fonts 面板,在 Firefox 上为 Fonts 选项卡)。对于 Firefox,我猜测它使用了 此代码,它似乎调用了内部 API。
我正在寻找任何符合 DOM(或供应商特定)标准的方法来从 JavaScript 中获取确切的字体,或者其他方式。如果这意味着编写浏览器扩展程序/插件来提供 API/注入信息/任何内容以便页面中的代码访问,那就是最坏的情况,但也可以接受。

只是出于好奇,什么是“多语言”?它的确切问题是什么?Multilingual如何干扰元素font-family的计算样式?(字体族是字体族,无论您使用英文还是中文) - Roko C. Buljan
我之所以说多语言,是因为这很明显。它不会影响字体系列。例如,就像你说中文...如果“好”出现在被CSS设置为courier的文本节点中,浏览器将使用任何系统字体。它是一个浏览器,会做一些额外的工作,我想知道是否发生了这种情况。 - beatak
1个回答

1
你可以使用hack:主要思路是将内联元素的大小与某些给定字体进行比较。一个应该使用完整的font-family值,另一个只使用单个font-family。这里有一个概念证明,它工作得相当不错。
// Look at the fiddle for full working code
function createFontTester(fontFamily) {
  var container = document.createElement('div');
  var tester = document.createElement('div');

  container.style.position = 'absolute';
  container.style.overflow = 'auto';
  container.style.visibility = 'hidden';

  tester.style.fontFamily = fontFamily;
  tester.style.display = 'inline';
  tester.style.visibility = 'hidden';

  // The size should be big enough to make a visual difference
  tester.style.fontSize = '100px'; 

  // Reset and prevent line breaks
  tester.style.fontWeight = 'normal';
  tester.style.fontStyle = 'normal';
  tester.style.letterSpacing = 'normal';
  tester.style.lineHeight = 'normal';
  tester.style.whiteSpace = 'nowrap';

  document.body.appendChild(container);
  container.appendChild(tester);

  return tester;
}

请注意,有些字体非常相似,大多数字符占用的空间相同。例如Helvetica和Arial:字符宽度大多相同,高度略有不同,因此我使用了较大的字号。
这种方法可能不是万无一失的,但适用于我能想到的所有字体系列。
更新:我在Github上制作了这个小库,可以处理更多的用例。

如果你要进行暴力检查,使用 canvas 会更好,我个人认为,首先用默认字体填充文本(fillText()),然后检查 canvas 的图像数据(imageData),最后与你的所有字体进行比较。但是,说真的,你打算下载整个互联网上的所有字体吗? - Kaiido
我没有下载任何东西,你是什么意思?话说,画布的想法很有趣。 - Julien Cabanès
也许我误解了,如果是这样,我道歉。但是你的想法似乎对我来说有点蛮力,因此你必须检查系统中的每种字体。但是,您无法获取系统上可用的所有字体列表,因此为了获取其中一些字体,您将不得不下载它们,对吗?就像在我的浏览器中,我使用SourceCodePro字体作为等宽字体,你的概念证明只向我展示了等宽字体,但默认字体在我的系统上是Courier。 OP的请求与之相同,因为他要求CJK字符,默认的CJK字体不能显示相同的字符集,并且可能会使用多个字体来显示单个文本。 - Kaiido
你说得对:我无法列出所有可用的字体(除了使用Flash,我猜),所以我没有这样做。我的做法是循环遍历字体列表中的每个单一字体系列,并将每个字体与列表进行比较。如果大小不同,则意味着回退,因此不可用。我找不到你的默认“等宽字体”,我能够猜测的是浏览器的回退。在你的情况下,POC无法显示Courier,因为它没有在声明中。如果你没有列出的任何字体,则最终回退是“等宽字体”,并且它会准确地显示给你,无论实际字体是Courier还是SourceCodePro。 - Julien Cabanès

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接