如何在网页字体加载后收到通知
How to be notified once a web font has loaded
Google的Web Fonts API提供了一种方法来定义当字体加载完成或无法加载时执行的回调函数。是否有一种方法来实现类似的使用CSS3网页字体(@font-face)?
2015更新
Chrome 35+和Firefox 41+实现CSS字体加载API (MDN, W3C)。调用document.fonts
来获得一个FontFaceSet对象,它有一些有用的api来检测字体的加载状态:
-
check(fontSpec)
-返回给定字体列表中的所有字体是否已加载并可用。fontSpec
采用CSS字体简写语法。
示例:document.fonts.check('bold 16px Roboto'); // true or false
-
document.fonts.ready
-返回一个承诺,表明字体加载和布局操作已经完成。
示例:document.fonts.ready.then(function () { /*... all fonts loaded...*/ });
下面的代码片段显示了这些api,加上document.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,请查看可用的填充或支持库:
- Web Font Loader -由Google和Adobe开发
- FontFaceOnload -打火机,类似于Web字体加载器
- FontLoader - polyfill
在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
});
Google Web Fonts API(和Typekit)使用的JS库可以在没有WebFont Loader服务的情况下使用。
它定义了您所请求的回调,以及更多。
2017更新
截至2017年,JS库FontFaceObserver绝对是最好的,最轻量级的跨浏览器解决方案。它还公开了基于promise的.load()
接口。
我创建了两个方法来检查特定的字体。第一种方法是最好的,因为它直接使用'fonts'接口和'check'方法。第二种方法没有那么好,但仍然有效,因为它通过比较使用默认字体的文本和使用新字体的文本的大小来直接检测DOM中的差异。虽然很罕见,但有可能字体大小非常接近而不会触发事件,但我认为这种可能性很小。如果发生这种情况,您可以添加另一个span来检查衬线字体之间的差异。
(虽然它是纯javascript,但它可以与React一起工作)
方法1
const fontName = "Fira Sans Condensed",
maxTime = 2500 // 2.5s
// EXAMPLE 1
fontOnload(fontName).then(() => {
console.log("success")
})
// EXAMPLE 2
fontOnload(fontName, maxTime).then(() => {
console.log("success")
}).catch(() => {
console.log("timeout")
})
async function fontOnload(fontName, maxTime = Infinity, timeInterval = 10) {
const startTime = performance.now()
return new Promise((resolve, reject) => {
setInterval(() => {
const currentTime = performance.now(),
elapsedTime = currentTime - startTime
if (document.fonts.check("12px " + fontName)) {
resolve(true)
} else if (elapsedTime >= maxTime) {
reject(false)
}
}, timeInterval)
})
}
方法2
const fontName = "Fira Sans Condensed",
maxTime = 2500 // 2.5s
// EXAMPLE 1
fontOnloadDOM(fontName).then(() => {
console.log("success")
})
// EXAMPLE 2
fontOnloadDOM(fontName, maxTime).then(() => {
console.log("success")
}).catch(() => {
console.log("timeout")
})
async function fontOnloadDOM(fontName, maxTime = Infinity, timeInterval = 10) {
return new Promise((resolve, reject) => {
const startTime = performance.now(),
abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
mainStyle = "font-size:24px!important;display:inline!important;font-family:",
body = document.body,
container = document.createElement("div"),
span1 = document.createElement("span"),
span2 = document.createElement("span")
container.classList.add("font-on-load")
container.setAttribute("style", "display:block!important;position:absolute!important;top:-9999px!important;left:-9999px!important;opacity:0!important;")
span1.setAttribute("style", mainStyle + "sans-serif!important;")
span2.setAttribute("style", mainStyle + "'"" + fontName + "'",sans-serif!important;")
span1.innerText = abc.repeat(3)
span2.innerText = abc.repeat(3)
container.append(span1, span2)
body.append(container)
const interval = setInterval(() => {
const currentTime = performance.now(),
elapsedTime = currentTime - startTime,
width1 = span1.clientWidth || span1.getBoundingClientRect().width,
width2 = span1.clientWidth || span2.getBoundingClientRect().width,
diffWidths = Math.abs(width1 - width2)
if (diffWidths > 9) {
clearInterval(interval)
resolve(true)
} else if (elapsedTime >= maxTime) {
clearInterval(interval)
reject(false)
}
}, timeInterval)
})
}
窗口。加载事件将在所有内容加载完毕时触发-应该包括字体所以你可以用它作为回叫。但是如果你决定使用web字体加载器
,我认为你不必这样做除了google, typekit,Ascender和monotype选项,在那里也是一个自定义模块,可以加载任何网页字体的样式表提供者。
WebFontConfig = {custom: {family: ['OneFont', 'AnotherFont'],url: ['http://myotherwebfontprovider.com/stylesheet1.css',"http://yetanotherwebfontprovider.com/stylesheet2.css"}};
无论您指定哪个提供程序,库都发送相同的事件。
- angularJS,一个部分或模态通知,加载几秒钟后就会消失
- 当子窗口打开并完成加载时得到通知
- javascript检查加载的URL并发出通知
- 在Phonegap中加载通知
- 通知系统,每次重新加载时都会在回调时触发 Firebase
- 将 jQuery 加载到 iframe 中,并在加载时收到通知
- 如何在加载下一页时保持 toastr.js 通知打开状态
- JQuery-在加载时触发通知,而不是onClick
- facebook评论加载通知
- 如何用JavaScript在加载视图中删除所有Chrome通知
- 当AngularJS应用被加载时得到通知
- JQuery加载,通知调用窗口
- 无法加载数据URL为chrome浏览器的GCM推送通知'notificationclick'事件
- 如何通知绑定处理程序内容已完全加载
- javascript通知当脚本在IE中动态加载时
- D3.js -在AJAX请求期间添加加载通知
- 正在收到有关iframe加载的通知
- 我必须重新加载chrome扩展以显示通知
- Chrome 的预提取功能会重新加载桌面设备通知
- Jquery在页面加载时获取桌面通知