如何知道字体(@font-face)是否已经加载?

IT技术 javascript jquery css font-face font-awesome
2021-01-29 08:03:23

我正在使用 Font-Awesome,但在未加载字体文件时,图标显示为 。

因此,我希望display:none在未加载文件时具有这些图标

@font-face {
  font-family: "FontAwesome";
  src: url('../font/fontawesome-webfont.eot');
  src: url('../font/fontawesome-webfont.eot?#iefix') format('eot'), url('../font/fontawesome-webfont.woff') format('woff'), url('../font/fontawesome-webfont.ttf') format('truetype'), url('../font/fontawesome-webfont.svg#FontAwesome') format('svg');
  font-weight: normal;
  font-style: normal;
}

我怎么知道这些文件已经加载,我终于可以显示图标了?

编辑: 我不是在页面加载(onload)时说话,因为字体可以在整个页面之前加载。

6个回答

现在在 GitHub 上:https : //github.com/patrickmarabeas/jQuery-FontSpy.js

本质上,该方法通过比较两种不同字体中字符串的宽度来工作。我们使用 Comic Sans 作为测试字体,因为它是最不同的网络安全字体,希望与您将使用的任何自定义字体有足够的不同。此外,我们使用了非常大的字体大小,因此即使是很小的差异也会很明显。计算 Comic Sans 字符串的宽度后,字体系列将更改为您的自定义字体,并回退到 Comic Sans。勾选时,如果字符串元素宽度相同,则仍然使用Comic Sans的fallback字体。如果没有,您的字体应该是可操作的。

我将字体加载检测的方法改写为一个 jQuery 插件,旨在让开发人员能够根据字体是否已加载来设置元素样式。添加了故障安全计时器,因此如果自定义字体无法加载,用户不会没有内容。这只是糟糕的可用性。

我还通过包含类的添加和删除,对字体加载期间和失败时发生的事情进行了更好的控制。您现在可以对字体执行任何您喜欢的操作。我只建议修改字体大小、行距等,以使您的回退字体尽可能接近自定义,这样您的布局保持完整,并且用户获得预期的体验。

这是一个演示:http : //patrickmarabeas.github.io/jQuery-FontSpy.js

将以下内容放入 .js 文件并引用它。

(function($) {

    $.fontSpy = function( element, conf ) {
        var $element = $(element);
        var defaults = {
            font: $element.css("font-family"),
            onLoad: '',
            onFail: '',
            testFont: 'Comic Sans MS',
            testString: 'QW@HhsXJ',
            delay: 50,
            timeOut: 2500
        };
        var config = $.extend( defaults, conf );
        var tester = document.createElement('span');
            tester.style.position = 'absolute';
            tester.style.top = '-9999px';
            tester.style.left = '-9999px';
            tester.style.visibility = 'hidden';
            tester.style.fontFamily = config.testFont;
            tester.style.fontSize = '250px';
            tester.innerHTML = config.testString;
        document.body.appendChild(tester);
        var fallbackFontWidth = tester.offsetWidth;
        tester.style.fontFamily = config.font + ',' + config.testFont;
        function checkFont() {
            var loadedFontWidth = tester.offsetWidth;
            if (fallbackFontWidth === loadedFontWidth){
                if(config.timeOut < 0) {
                    $element.removeClass(config.onLoad);
                    $element.addClass(config.onFail);
                    console.log('failure');
                }
                else {
                    $element.addClass(config.onLoad);
                    setTimeout(checkFont, config.delay);
                    config.timeOut = config.timeOut - config.delay;
                }
            }
            else {
                $element.removeClass(config.onLoad);
            }
        }
        checkFont();
    };

    $.fn.fontSpy = function(config) {
        return this.each(function() {
            if (undefined == $(this).data('fontSpy')) {
                var plugin = new $.fontSpy(this, config);
                $(this).data('fontSpy', plugin);
            }
        });
    };

})(jQuery);

将其应用于您的项目

.bannerTextChecked {
        font-family: "Lobster";
        /* don't specify fallback font here, do this in onFail class */
}

$(document).ready(function() {

    $('.bannerTextChecked').fontSpy({
        onLoad: 'hideMe',
        onFail: 'fontFail anotherClass'
    });

});

移除那个 FOUC!

.hideMe {
    visibility: hidden !important;
}

.fontFail {
    visibility: visible !important;
    /* fall back font */
    /* necessary styling so fallback font doesn't break your layout */
}

编辑:FontAwesome 兼容性已被删除,因为它无法正常工作并遇到不同版本的问题。可以在这里找到一个 hacky 修复:https : //github.com/patrickmarabeas/jQuery-FontFaceSpy.js/issues/1

我需要用它来解决一个问题,我在加载字体之前使用 iScroll 计算错误的元素大小。但我没有使用 jQuery,所以做了一个 vanilla js 版本:github.com/keithswright/vanilla-fontspy似乎对我有用
2021-03-13 08:03:23
在任何情况下,比较字符长度对许多字体都不起作用,因为许多“复制”字体被设计为具有相等的长度例如,Arial、Helvetica 和 Liberation Sans 的所有字符都具有相同的字符宽度。另见en.wikipedia.org/wiki/Arial到目前为止,似乎使用画布逐像素检查可能是唯一的万无一失的选择.....
2021-03-21 08:03:23
比较字体长度...这也是 WebFont Loader(参见其他答案)所做的吗?
2021-03-29 08:03:23
@Pacerier - 请注意,只有您选择的测试和您选择的加载字体需要不同的长度。因此,除非 Comic Sans 有很多字体与字符宽度相同,否则在大多数情况下这应该仍然有效。
2021-04-04 08:03:23

试试由 Google 和 Typekit 开发的WebFont Loader ( github repo )。

本示例首先以默认衬线字体显示文本;然后在字体加载后,它以指定的字体显示文本。(此代码在所有其他现代浏览器中重现了 Firefox 的默认行为。)

这是解决其他人的不同方法。

我正在使用 FontAwesome 4.1.0 来构建 WebGL 纹理。这让我想到使用一个小画布来渲染一个 fa-square,然后检查该画布中的一个像素以测试它是否已加载:

function waitForFontAwesome( callback ) {
   var retries = 5;

   var checkReady = function() {
      var canvas, context;
      retries -= 1;
      canvas = document.createElement('canvas');
      canvas.width = 20;
      canvas.height = 20;
      context = canvas.getContext('2d');
      context.fillStyle = 'rgba(0,0,0,1.0)';
      context.fillRect( 0, 0, 20, 20 );
      context.font = '16pt FontAwesome';
      context.textAlign = 'center';
      context.fillStyle = 'rgba(255,255,255,1.0)';
      context.fillText( '\uf0c8', 10, 18 );
      var data = context.getImageData( 2, 10, 1, 1 ).data;
      if ( data[0] !== 255 && data[1] !== 255 && data[2] !== 255 ) {
         console.log( "FontAwesome is not yet available, retrying ..." );
         if ( retries > 0 ) {
            setTimeout( checkReady, 200 );
         }
      } else {
         console.log( "FontAwesome is loaded" );
         if ( typeof callback === 'function' ) {
            callback();
         }
      }
   }

   checkReady();
};

因为它使用画布,所以它需要一个相当现代的浏览器,但它可能也适用于 IE8 以及 polyfill。

在 KonvaJS 中加载 font-awesome 时我面临同样的问题
2021-04-04 08:03:23

实际上,有一个很好的方法可以了解所有字体是否开始下载或加载完毕并陷入某些错误,但不仅仅是针对特定字体,请注意以下代码:

document.fonts.onloading = () => {
  // do someting when fonts begin to download
};
document.fonts.onloadingdone = () => {
  // do someting when fonts are loaded completely
};
document.fonts.onloading = () => {
  // do someting when fonts fall into some error
};

还有一个返回的选项,Promise它可以处理.then函数:

document.fonts.ready
 .then(() => console.log('do someting at the final with each status'))
@GuyPassy,我不知道 IE11 是什么!!
2021-03-15 08:03:23
IE11 不支持,不幸的是它仍然与 Windows Server 捆绑在一起
2021-03-20 08:03:23
谢谢。它完全有效!但是我需要通过在某处放置一个使用该字体的 <span> 元素来触发字体加载。
2021-03-31 08:03:23
@AmerllicA 我希望有一天我能如此幸运
2021-03-31 08:03:23

这是了解@font-face 是否已经加载而根本无需使用计时器的另一种方法:当精心设计的元素的大小发生更改时,利用“滚动”事件接收瞬时事件。

我写了一篇关于它是如何完成博客文章,并在 Github 上发布了该