交换 css 字体时是否发出 js 事件?

Is a js event emitted when a css font is swapped?

我能否判断字体何时已成功(或以其他方式)加载,然后使用 JS 进行操作?

上下文

我正在使用 playwright 打印一系列文档。我目前正在加载这些字体 https://fonts.googleapis.com/css2?family=Raleway:wght@100;300;600&display=swap,有时 waitUntil="networkidle" 会在字体加载之前完成 ½ 秒的等待,导致文档以后备字体打印。

参考资料

我读过 this: Controlling Font Performance with font-display and this: Navigating & waiting,并进行了大量搜索,但无济于事。

可能的解决方法

有没有简单的方法?

是的,您可以使用 Font Face Observer 来执行此操作,它是一个小型的@font-face,用于监视字体的加载。这并不限制您使用任何类型的字体加载。

例如

var font = new FontFaceObserver('My Family', {
  weight: 400
});

font.load().then(function () {
  console.log('Font is available');
}, function () {
  console.log('Font is not available');
});

如果您想了解更多信息,请查看 https://portalzine.de/dev/options-to-detect-when-a-font-face-has-been-loaded/

希望能回答您的问题。

christopher-holder's answer pointed me at that useful article from Portalzine中的link。我使用了他们第一个选项的技术,即

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');
};

并使用 page.waitForFunction 将逻辑移动到 Playwright 脚本中,如下所示:

await page.goto(
  "file:///" + path.resolve(htmlFilename),
  (waitUntil = "networkidle")
);
await page.waitForFunction(() => document.fonts.check("1em Raleway"));

这会等待页面加载完成,并等待网络安静 ½ 秒,然后检查字体是否已加载。

FontFaceObserver 看起来不错,但是这种方法保留了编剧脚本中的打印逻辑并且不触及文档本身,感觉更干净。

这可能是腰带和牙套,我会在更彻底地测试后更新这个答案。

这是我用来重新调整滚动位置的一段 JS 代码,以针对 :target scroll-margin 和不同于后备字体的网络字体进行调整:

if (location.hash)
{
    var targetElement = document.getElementById(location.hash.substring(1));
    if (targetElement && targetElement.scrollIntoView)
    {
        // scroll to correct position immediately
        targetElement.scrollIntoView({block:"start", behavior:"auto"});

        // Note that because the page might be rendered before
        // web fonts are ready and web fonts may/will cause
        // layout shift, we'll need to re-adjust the scroll
        // position when fonts are ready:
        try
        {
            var fontsReady = document.fonts.ready;
            fontsReady.then(function ()
            {
                console.log('Font loading complete');
                // process full event loop and re-adjust the scroll:
                window.setTimeout(function ()
                {
                    targetElement.scrollIntoView({block:"nearest", behavior:"smooth"});
                }, 0);
            });
        }
        catch (e)
        {
            console && console.error && console.error(e);
            console && console.log && console.log("This browser doesn't support observing font loading, scroll position may be incorrect.");
        }
    }
}

根据您的用例和预期的事件时间,对 scrollIntoView() 的两次调用都可以使用 behavior:"auto"behavior:"smooth"。另请注意,用户可能已经在使用后备字体渲染内容和完成网络字体加载之间滚动了视口,因此您可能需要添加额外的代码来侦听滚动事件,并避免在用户已经滚动时换入网络字体时滚动任何内容到另一个位置。