Javascript 如何在 Web 字体加载后收到通知
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5680013/
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
How to be notified once a web font has loaded
提问by Daniel Wagner
Google's Web Fonts API offers a way to define callback functions to be executed if a font has finished loading, or couldn't be loaded etc. Is there a way to achieve something similar using CSS3 web fonts (@font-face)?
Google 的 Web Fonts API 提供了一种方法来定义在字体已完成加载或无法加载等情况下要执行的回调函数。有没有办法使用 CSS3 网络字体(@font-face)实现类似的功能?
回答by Dan Dascalescu
2015 Update
2015年更新
Chrome 35+ and Firefox 41+ implement the CSS font loading API(MDN, W3C). Call document.fonts
to get a FontFaceSetobject, which has a few useful APIs for detecting the load status of fonts:
Chrome 35+ 和 Firefox 41+ 实现了CSS 字体加载 API(MDN,W3C)。调用document.fonts
获取一个FontFaceSet对象,该对象有几个有用的 API 用于检测字体的加载状态:
check(fontSpec)
- returns whether all fonts in the given font list have been loaded and are available. ThefontSpec
uses the CSS shorthand syntax for fonts.
Example:document.fonts.check('bold 16px Roboto'); // true or false
document.fonts.ready
- returns a Promiseindicating that font loading and layout operations are done.
Example:document.fonts.ready.then(function () { /*... all fonts loaded...*/ });
check(fontSpec)
- 返回给定字体列表中的所有字体是否已加载并可用。在fontSpec
使用的字体CSS缩写语法。
例子:document.fonts.check('bold 16px Roboto'); // true or false
document.fonts.ready
- 返回一个表示字体加载和布局操作已完成的Promise。
例子:document.fonts.ready.then(function () { /*... all fonts loaded...*/ });
Here's a snippet showing these APIs, plus document.fonts.onloadingdone
, which offers extra information about the font faces.
这是显示这些 API 的片段, plusdocument.fonts.onloadingdone
提供了有关字体外观的额外信息。
alert('Roboto loaded? ' + document.fonts.check('1em Roboto')); // false
document.fonts.ready.then(function () {
alert('All fonts in use by visible text have loaded.');
alert('Roboto loaded? ' + document.fonts.check('1em Roboto')); // true
});
document.fonts.onloadingdone = function (fontFaceSetEvent) {
alert('onloadingdone we have ' + fontFaceSetEvent.fontfaces.length + ' font faces loaded');
};
<link href='https://fonts.googleapis.com/css?family=Roboto:400,700' rel='stylesheet' type='text/css'>
<p style="font-family: Roboto">
We need some text using the font, for the font to be loaded.
So far one font face was loaded.
Let's add some <strong>strong</strong> text to trigger loading the second one,
with weight: 700.
</p>
IE 11 doesn't support the API. Look at available polyfills or support libraries if you need to support IE:
IE 11 不支持 API。如果您需要支持 IE,请查看可用的 polyfills 或支持库:
- Web Font Loader- developed by Google and Adobe
- FontFaceOnload- lighter, similar approach to Web Font Loader
- FontLoader- polyfill
- Web Font Loader- 由 Google 和 Adobe 开发
- FontFaceOnload- 与 Web Font Loader 类似的更轻量级的方法
- FontLoader-填充
回答by Thomas Bachem
Tested in Safari, Chrome, Firefox, Opera, IE7, IE8, IE9:
在 Safari、Chrome、Firefox、Opera、IE7、IE8、IE9 中测试:
function waitForWebfonts(fonts, callback) {
var loadedFonts = 0;
for(var i = 0, l = fonts.length; i < l; ++i) {
(function(font) {
var node = document.createElement('span');
// Characters that vary significantly among different fonts
node.innerHTML = 'giItT1WQy@!-/#';
// Visible - so we can measure it - but not on the screen
node.style.position = 'absolute';
node.style.left = '-10000px';
node.style.top = '-10000px';
// Large font size makes even subtle changes obvious
node.style.fontSize = '300px';
// Reset any font properties
node.style.fontFamily = 'sans-serif';
node.style.fontVariant = 'normal';
node.style.fontStyle = 'normal';
node.style.fontWeight = 'normal';
node.style.letterSpacing = '0';
document.body.appendChild(node);
// Remember width with no applied web font
var width = node.offsetWidth;
node.style.fontFamily = font;
var interval;
function checkFont() {
// Compare current width with original width
if(node && node.offsetWidth != width) {
++loadedFonts;
node.parentNode.removeChild(node);
node = null;
}
// If all fonts have been loaded
if(loadedFonts >= fonts.length) {
if(interval) {
clearInterval(interval);
}
if(loadedFonts == fonts.length) {
callback();
return true;
}
}
};
if(!checkFont()) {
interval = setInterval(checkFont, 50);
}
})(fonts[i]);
}
};
Use it like:
像这样使用它:
waitForWebfonts(['MyFont1', 'MyFont2'], function() {
// Will be called as soon as ALL specified fonts are available
});
回答by bpierre
The JS Library used by Google Web Fonts API (and Typekit) can be used without the service: WebFont Loader.
Google Web Fonts API(和 Typekit)使用的 JS 库可以在没有服务的情况下使用:WebFont Loader。
It defines callbacks for what you ask, and many more.
它为您的要求定义了回调,等等。
回答by fisch2
2017 Update
2017年更新
The JS library FontFaceObserveris definitely the best, most lightweight, cross-browser solution as of 2017. It also exposes a Promise-based .load()
interface.
JS 库FontFaceObserver绝对是 2017 年最好、最轻量级的跨浏览器解决方案。它还公开了一个基于 Promise 的.load()
接口。
回答by Shaun Hare
The window.load event will fire when everything has loaded - that should include fonts So you could use that as the call back. However I don't think you have to is you decide to use the web font loader as
window.load 事件将在所有内容都加载后触发 - 应该包括字体,因此您可以将其用作回调。但是我认为您不必决定使用网络字体加载器作为
In addition to the google, typekit, ascender and monotype options, there is also a custom module that can load a stylesheet from any web-font provider.
WebFontConfig = { custom: { families: ['OneFont', 'AnotherFont'], urls: [ 'http://myotherwebfontprovider.com/stylesheet1.css', 'http://yetanotherwebfontprovider.com/stylesheet2.css' ] } };
除了 google、typekit、ascender 和 monotype 选项之外,还有一个自定义模块可以从任何网络字体提供商加载样式表。
WebFontConfig = { custom: { family: ['OneFont', 'AnotherFont'], urls: ['http://myotherwebfontprovider.com/stylesheet1.css', 'http://yetanotherwebfontprovider.com/stylesheet2.css'] } };
The library sends the same events regardless of which provider you specify.
无论您指定哪个提供程序,库都会发送相同的事件。