如何在 Web 字体加载后收到通知

IT技术 javascript webfonts
2021-02-07 02:26:53

Google 的 Web Fonts API 提供了一种方法来定义在字体已完成加载或无法加载等情况下要执行的回调函数。有没有办法使用 CSS3 网络字体(@font-face)实现类似的功能?

5个回答

2015年更新

Chrome 35+ 和 Firefox 41+ 实现了CSS 字体加载 APIMDNW3C)。调用document.fonts获取一个FontFaceSet对象,该对象有几个有用的 API 用于检测字体的加载状态:

  • 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...*/ });

这是显示这些 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 不支持 API。如果您需要支持 IE,请查看可用的 polyfills 或支持库:

2021-03-16 02:26:53
您是否知道如何在 Angular2 中优雅地连接到它?我希望有一个ngAfterFontInitin ng2 界面,但没有...
2021-03-21 02:26:53
我能让这个工作的唯一方法是使用onloadingdone. .ready总是立即开火
2021-03-29 02:26:53
在我看来,只包含字体并不意味着加载将开始。您需要使用字体(例如在 html/CSS 或 JS 代码中),然后我才加载了字体。也就是说,当你想在 js 中使用它时,只是想在 JS 中加载字体是不够的
2021-04-01 02:26:53
在 Linux 上的 Firefox 44 中,它看起来check总是返回true: document.fonts.check('1em NoThisReallyDoesntExist')查看MDN 文档,它看起来像是一个实验性/不完整的功能。它似乎在 Chromium 中正常工作。
2021-04-03 02:26:53

在 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]);
    }
};

像这样使用它:

waitForWebfonts(['MyFont1', 'MyFont2'], function() {
    // Will be called as soon as ALL specified fonts are available
});
您可以将其设置为可见:隐藏,它仍然是可测量的
2021-03-13 02:26:53
不适用于 Chrome 版本 73.0.3683.86 - 在字体加载之前触发功能。仅使用网络节流“慢 3G”预设和 Chrome 进行测试,未检查其他浏览器。
2021-03-14 02:26:53
应该注意的是,如果字体系列的名称需要,则需要额外的引号: waitForWebfonts(['"Vectora W01 56 Italic"'],...);
2021-03-20 02:26:53
在 Chrome 版本 59.0.3071.86 中永远不会被调用
2021-04-03 02:26:53
每次加载的字体都会调用 callback() 函数,我想它应该只调用一次吗?
2021-04-10 02:26:53

Google Web Fonts API(和 Typekit)使用的 JS 库可以在没有服务的情况下使用:WebFont Loader

它为您的要求定义了回调,等等

从 Google 网站上看并不明显,但可以下载该库:github.com/typekit/webfontloader
2021-03-21 02:26:53

2017年更新

JS 库FontFaceObserver绝对是 2017 年最好、最轻量级的跨浏览器解决方案。它还公开了一个基于 Promise 的.load()接口。

@vintproykt 除非字体只有方形字符;) 至少我没有在 Google Material Icons 中找到任何非方形字符。
2021-03-20 02:26:53
@maersu 这很简单:根据这家伙所说的,只需从字体和var observe_fa = new FontFaceObserver('FontAwesome'); observe_fa.load('<SOME TEST ICON SYMBOLS GO HERE>').then(...).
2021-04-01 02:26:53
这个库在图标字体方面有一些问题github.com/bramstein/fontfaceobserver/issues/...
2021-04-04 02:26:53

window.load 事件将在所有内容都加载后触发 - 应该包括字体,因此您可以将其用作回调。但是我认为您不必决定使用网络字体加载器作为

除了 google、typekit、ascender 和 monotype 选项之外,还有一个自定义module可以从任何网络字体提供商加载样式表。

WebFontConfig = { custom: { family: ['OneFont', 'AnotherFont'], urls: ['http://myotherwebfontprovider.com/stylesheet1.css', 'http://yetanotherwebfontprovider.com/stylesheet2.css'] } };

无论您指定哪个提供程序,库都会发送相同的事件。

情况似乎并非如此:至少在 WebKit 中,该load事件可以在 Web 字体加载之前触发。
2021-04-08 02:26:53