Javascript 列出用户浏览器可以显示的每种字体
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3368837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
list every font a user's browser can display
提问by mattsh
Is there a way in javascript to obtain the names of all fonts (or font-families) that the browser can show? (I want to give the user a dropdown with a list of all available fonts, and allow the user to choose a font.) I'd prefer not to have to hardcode this list ahead of time or send it down from the server. (Intuitively, it seems like the browser should know what fonts it has and this should be exposed to javascript somehow.)
javascript中有没有办法获取浏览器可以显示的所有字体(或字体系列)的名称?(我想为用户提供一个包含所有可用字体列表的下拉列表,并允许用户选择一种字体。)我不想提前对此列表进行硬编码或从服务器发送下来。(直觉上,浏览器似乎应该知道它有什么字体,并且应该以某种方式暴露给 javascript。)
采纳答案by alex
The JavaScript version is a bit flaky. It gets fonts by iterating through known fonts and testing.
JavaScript 版本有点不稳定。它通过迭代已知字体和测试来获取字体。
The most accurate way (albeit having to use a propriety plugin) is to use Flash. Here you can get the list of fonts without having to test for them individually using dimensions.
最准确的方法(尽管必须使用专有插件)是使用 Flash。在这里,您可以获得字体列表,而无需使用尺寸单独测试它们。
You are going have to decide whether to have an exact list at the expense of not working on some devices ( iDevices, browsers without Flash plugin, etc), or a partial list with better support via JavaScript only.
您将不得不决定是否有一个确切的列表,但代价是不能在某些设备(iDevices、没有 Flash 插件的浏览器等)上工作,还是只通过 JavaScript 获得更好支持的部分列表。
回答by Marko
Yes there is! I'm so glad you asked this question because I now want to use this too.
就在这里!我很高兴你问这个问题,因为我现在也想使用它。
+1 for question, and here's your answer :)
+1 问题,这是您的答案:)
http://www.lalit.org/lab/javascript-css-font-detect
http://www.lalit.org/lab/javascript-css-font-detect
Codefrom http://www.lalit.org/wordpress/wp-content/uploads/2008/05/fontdetect.js?ver=0.3
来自http://www.lalit.org/wordpress/wp-content/uploads/2008/05/fontdetect.js?ver=0.3 的代码
/**
* JavaScript code to detect available availability of a
* particular font in a browser using JavaScript and CSS.
*
* Author : Lalit Patel
* Website: http://www.lalit.org/lab/javascript-css-font-detect/
* License: Apache Software License 2.0
* http://www.apache.org/licenses/LICENSE-2.0
* Version: 0.15 (21 Sep 2009)
* Changed comparision font to default from sans-default-default,
* as in FF3.0 font of child element didn't fallback
* to parent element if the font is missing.
* Version: 0.2 (04 Mar 2012)
* Comparing font against all the 3 generic font families ie,
* 'monospace', 'sans-serif' and 'sans'. If it doesn't match all 3
* then that font is 100% not available in the system
* Version: 0.3 (24 Mar 2012)
* Replaced sans with serif in the list of baseFonts
*/
/**
* Usage: d = new Detector();
* d.detect('font name');
*/
var Detector = function() {
// a font will be compared against all the three default fonts.
// and if it doesn't match all 3 then that font is not available.
var baseFonts = ['monospace', 'sans-serif', 'serif'];
//we use m or w because these two characters take up the maximum width.
// And we use a LLi so that the same matching fonts can get separated
var testString = "mmmmmmmmmmlli";
//we test using 72px font size, we may use any size. I guess larger the better.
var testSize = '72px';
var h = document.getElementsByTagName("body")[0];
// create a SPAN in the document to get the width of the text we use to test
var s = document.createElement("span");
s.style.fontSize = testSize;
s.innerHTML = testString;
var defaultWidth = {};
var defaultHeight = {};
for (var index in baseFonts) {
//get the default width for the three base fonts
s.style.fontFamily = baseFonts[index];
h.appendChild(s);
defaultWidth[baseFonts[index]] = s.offsetWidth; //width for the default font
defaultHeight[baseFonts[index]] = s.offsetHeight; //height for the defualt font
h.removeChild(s);
}
function detect(font) {
var detected = false;
for (var index in baseFonts) {
s.style.fontFamily = font + ',' + baseFonts[index]; // name of the font along with the base font for fallback.
h.appendChild(s);
var matched = (s.offsetWidth != defaultWidth[baseFonts[index]] || s.offsetHeight != defaultHeight[baseFonts[index]]);
h.removeChild(s);
detected = detected || matched;
}
return detected;
}
this.detect = detect;
};
Summary
概括
How does it work?
This code works on the simple principle that each character appears differently in different fonts. So different fonts will take different width and height for the same string of characters of same font-size.
它是如何工作的?
此代码的工作原理很简单,即每个字符在不同字体中的显示方式不同。因此,对于相同字体大小的同一字符串,不同的字体将采用不同的宽度和高度。
回答by MPC
<SCRIPT>
function getFonts()
{
var nFontLen = dlgHelper.fonts.count;
var rgFonts = new Array();
for ( var i = 1; i < nFontLen + 1; i++ )
rgFonts[i] = dlgHelper.fonts(i);
rgFonts.sort();
for ( var j = 0; j < nFontLen; j++ )
document.write( rgFonts[j] + "<BR>" );
}
</SCRIPT>
<BODY onload="getFonts()">
<OBJECT id=dlgHelper CLASSID="clsid:3050f819-98b5-11cf-bb82-00aa00bdce0b" width="0px" height="0px">
</OBJECT>
回答by Chris Chiasson
Go to deviceinfo.meand click on the font detection button.
转到deviceinfo.me并单击字体检测按钮。
回答by kofifus
I added two methods to Lalit Patel's Detector above :
我在上面的 Lalit Patel 的 Detector 中添加了两种方法:
- addFont(family, stylesheetUrl, ruleString) -> detects if the font 'family' exists, if not adds a stylesheet loading the font using either stylesheetUrl if given or otherwise ruleString
- addFontsArr(arr) -> adds an array of fonts
- addFont(family, stylesheetUrl, ruleString) -> 检测字体“family”是否存在,如果不存在,则使用 stylesheetUrl(如果给定)或其他 ruleString 添加样式表加载字体
- addFontsArr(arr) -> 添加字体数组
With this you can do:
有了这个,你可以:
fonts = [ 'Arial', 'Arial Black', { family: 'Lato', stylesheetUrl: 'https://fonts.googleapis.com/css?family=Lato'}, 'Leelawadee UI']
(new FontDetector()).addFontsArr(fonts);
code:
代码:
/**
* JavaScript code to detect available availability of a
* particular font in a browser using JavaScript and CSS.
*
* Author : Lalit Patel
* Website: http://www.lalit.org/lab/javascript-css-font-detect/
* License: Apache Software License 2.0
* http://www.apache.org/licenses/LICENSE-2.0
* Version: 0.15 (21 Sep 2009)
* Changed comparision font to default from sans-default-default,
* as in FF3.0 font of child element didn't fallback
* to parent element if the font is missing.
* Version: 0.2 (04 Mar 2012)
* Comparing font against all the 3 generic font families ie,
* 'monospace', 'sans-serif' and 'sans'. If it doesn't match all 3
* then that font is 100% not available in the system
* Version: 0.3 (24 Mar 2012)
* Replaced sans with serif in the list of baseFonts
*/
/**
* Usage: d = new Detector();
* d.detect('font name');
*/
function FontDetector() {
this.detect = detect;
this.addFont = addFont;
this.addFontsArr = addFontsArr;
// a font will be compared against all the three default fonts.
// and if it doesn't match all 3 then that font is not available.
var baseFonts = ['monospace', 'sans-serif', 'serif'];
//we use m or w because these two characters take up the maximum width.
// And we use a LLi so that the same matching fonts can get separated
var testString = "mmmmmmmmmmlli";
//we test using 72px font size, we may use any size. I guess larger the better.
var testSize = '72px';
var h = document.getElementsByTagName("body")[0];
// create a SPAN in the document to get the width of the text we use to test
var s = document.createElement("span");
s.style.fontSize = testSize;
s.innerHTML = testString;
var defaultWidth = {};
var defaultHeight = {};
for (var index in baseFonts) {
//get the default width for the three base fonts
s.style.fontFamily = baseFonts[index];
h.appendChild(s);
defaultWidth[baseFonts[index]] = s.offsetWidth; //width for the default font
defaultHeight[baseFonts[index]] = s.offsetHeight; //height for the defualt font
h.removeChild(s);
}
function detect(font) {
var detected = false;
for (var index in baseFonts) {
s.style.fontFamily = font + ',' + baseFonts[index]; // name of the font along with the base font for fallback.
h.appendChild(s);
var matched = (s.offsetWidth != defaultWidth[baseFonts[index]] || s.offsetHeight != defaultHeight[baseFonts[index]]);
h.removeChild(s);
detected = detected || matched;
}
return detected;
}
function addFont(family, stylesheetUrl, ruleString) {
if (detect(family)) {
//console.log('using internal font '+family);
return true;
}
if (stylesheetUrl) {
console.log('added stylesheet '+stylesheetUrl);
var head = document.head, link = document.createElement('link');
link.type = 'text/css';
link.rel = 'stylesheet';
link.href = stylesheetUrl;
head.appendChild(link);
return true;
}
if (ruleString) {
console.log('adding font rule:'+rule);
var newStyle = document.createElement('style');
newStyle.appendChild(document.createTextNode(rule));
document.head.appendChild(newStyle);
return true;
}
console.log('could not add font '+family);
}
function addFontsArr(arr) {
arr.forEach(a => typeof a==='string' ? addFont(a) : addFont(a.family, a.stylesheetUrl, a.ruleString));
}
};
回答by Stoffe
In my search for this, I also found Font.js, which adds a Font object much like Image, so it's possible to check when a font is actually ready to use. Also works on installed/system fonts. Downside is IE9+ only due to needing Object.defineProperty(other browsers have it), but if you are doing modern web, this seems like an even better option. (I will, sadly, have to go with the answer above, upvoted and moving on for now. :))
在我的搜索中,我还找到了Font.js,它添加了一个很像 Image 的 Font 对象,因此可以检查字体何时真正可以使用。也适用于已安装/系统字体。缺点是 IE9+ 只是因为需要Object.defineProperty(其他浏览器都有),但如果你正在做现代网络,这似乎是一个更好的选择。(可悲的是,我将不得不接受上面的答案,现在已经投票并继续前进。:))
回答by fzzylogic
Maybe this could be done in a completely different way, using a spritesheet with known font images for a specific character and comparing that with snapshots of a canvas element on which the same character is drawn with what the browser reports as the same font. The comparison may be done with something like resemble.js.
也许这可以以完全不同的方式完成,使用具有特定字符的已知字体图像的 spritesheet,并将其与画布元素的快照进行比较,在该元素上绘制了相同的字符,浏览器报告为相同的字体。比较可以用类似like.js 的东西来完成。
This is slower, but should also allow us to detect when the browser is lying.
这比较慢,但也应该允许我们检测浏览器何时在撒谎。
回答by AFF
I have recently noticed that if I set the context.font value for an HTML5 canvas, to something invalid, such as "junk", the change is ignored by the canvas. I do not know if this is browser specific, but it seems to work this way on Chrome. I have also seen other posts (HTML 5 canvas font being ignored) that indicate it happens in other browsers.
我最近注意到,如果我将 HTML5 画布的 context.font 值设置为无效的值,例如“垃圾”,画布会忽略更改。我不知道这是否特定于浏览器,但它似乎在 Chrome 上以这种方式工作。我还看到其他帖子(HTML 5 画布字体被忽略)表明它发生在其他浏览器中。
One could then write a string out with the default value, which I believe is "10px sans serif" (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/font), set the font to one you are testing and write the string again. If it is the same as the first drawing, then the font is not available.
然后可以用默认值写出一个字符串,我认为它是“10px sans serif”(https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/font),设置字体到您正在测试并再次写入字符串的一个。如果与第一张图相同,则字体不可用。

