【问题标题】:Using jQuery to know when @font-face fonts are loaded?使用 jQuery 知道何时加载 @font-face 字体?
【发布时间】:2017-06-06 15:57:34
【问题描述】:

我正在使用@font-face,我讨厌Firefox 显示默认字体,等待加载@font-face 字体,然后替换它。所以整个页面都以新字体闪烁。

Webkit 浏览器只是在加载字体之前不显示文本,这样看起来更干净。

所以,我想知道 jQuery 是否可以帮助我知道页面上的所有数据何时加载,包括 @font-face 文件,以便我可以显示我的文本?是否有一个 jQuery 方法可以告诉我什么时候加载所有内容?

【问题讨论】:

  • 我差点发了一个答案,但实在是太蹩脚了,我想我会等着看有没有聪明人知道做这件事的好方法。
  • @Pointy - 哈哈,没关系。
  • 为了记录,我放弃的答案是建议用计时器观察一些测试元素(可能隐藏)的大小,然后等待它的大小何时发生变化。也就是说,您在尝试加载字体之前 启动计时器,然后当计时器例程(每 50 毫秒左右运行一次)看到某个框的大小发生了变化时,它就知道字体一定已经到了。
  • 哦,哦,哦——你可以加载带有 Image 对象的字体文件,当 onload 触发时,你可以翻转一个开关来启用 CSS 并显示样式元素。
  • ...如果响应不是图像,则“load”除外...

标签: javascript jquery css font-face


【解决方案1】:

我使用此功能 - 在 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 + ', sans-serif';

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

【讨论】:

  • 出色的不臃肿解决方案。有没有人遇到过不会导致大小改变的字体(因此锁定!也许 max_time_to_wait 会是谨慎的......)?
  • 为每种字体创建一个setInterval() 似乎有点不幸。宁愿有一个setInterval() 来检查所有仍需要检查的字体。
  • 在 Chrome 39 中不起作用。调用回调时,字体已加载,但我的页面上有许多元素仍以备用字体 (Arial) 呈现。
  • 我发现这个解决方案有一个严重的错误,基本上有时不起作用,因为一旦你更改了尚未加载字体的fontFamily,它就会开始使用继承的字体( span,由于任何 CSS 规则)所以它说它已经改变,所以它在加载 web 字体之前执行回调。我刚刚提交了一个修复程序。
  • 这段代码有问题;它会多次运行回调,因为您为每个字体设置间隔 - 但只有在所有字体加载后它们才会被清除。将if(interval) { clearInterval(interval);} 移到++loadedFonts; 之后可以解决问题。
【解决方案2】:

好的,这很容易。基本上我只是将我的文本设置为:

a.main {visibility: hidden;}

然后添加:

$(window).bind("load", function() {
       $('#nav a.main').addClass('shown');
});

然后确保以下内容也在我的 css 文件中:

a.main.shown {visibility: visible;}

【讨论】:

  • @Chris - 这些天我们真的那么担心用户关闭 js 吗?你生活在1990年代吗?我的目标用户不会关闭js。
  • 在我自己的网站上我不在乎关闭 JavaScript 的用户是否会丢失很多功能,但如果你有它导致页面的关键部分无缘无故消失 - 这是一个原因我认为值得关注。
  • 如果有问题可以使用这个 ;- )
  • 不需要刻薄,只需使用:
  • load 事件等待 Firefox 中的字体文件,而不是 WebKit。所以这是不可靠的。
【解决方案3】:

您不应该使用$(window).bind('load') - 这将等待整个页面加载(这可能是您想要的),而不仅仅是字体。如果您想控制@font-faces 的加载过程,请使用由 Google 和 Typekit 开发的 WebFont Loader。

您可以将它与 Google Font API、typekit 和您自己的 webfont 提供商 - 您一起使用(尽管我自己从未尝试过,因为我是 Typekit 用户。

在此处阅读:http://code.google.com/apis/webfonts/docs/webfont_loader.html 和此处:http://blog.typekit.com/2010/05/19/typekit-and-google/

【讨论】:

  • jQuery 并不是所有 JavaScript 问题的答案,而 WebFont Loader 是适合这项工作的(其他)工具的完美示例。 :-)
  • @SixtenOtto 不,这个解决方案适用于字体
【解决方案4】:

我使用谷歌网页字体(Crete Round Regular 和 Open Sans Regular with Bold)

你可以使用这个:

var fonts = $.Deferred();
WebFontConfig = { google: { families: [ 'Crete+Round::latin', 'Open+Sans:400,700:latin' ] } , active : function() { fonts.resolve(); } };
(function() {
    var wf = document.createElement('script');
    wf.src = ('https:' == document.location.protocol ? 'https' : 'http') + '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
    wf.type = 'text/javascript';
    wf.async = 'true';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(wf, s);
})();
fonts.done(function(){ alert('fonts'); });

或者这个:

WebFontConfig = { google: { families: [ 'Crete+Round::latin', 'Open+Sans:400,700:latin' ] } , active : function() { alert('fonts'); } };
(function() {
    var wf = document.createElement('script');
    wf.src = ('https:' == document.location.protocol ? 'https' : 'http') + '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
    wf.type = 'text/javascript';
    wf.async = 'true';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(wf, s);
})();

请注意,在第一个选项中,我使用了 jQuery Deferred Object。

【讨论】:

    【解决方案5】:

    也许……

    创建一个 z-index: -10 div 并用大量文本填充它(使用“普通”字体)。在 document.ready() 或其他事件:

    var originalnumber = $( div ).width() + $( div ).height() + $( div ).offset().top + $( div ).offset().left;
    
    $( div ).css( 'font-family', 'MyPrettyWebfont' );
    
    var interval = setInterval( function() {
        var number = $( div ).width() + $( div ).height() + $( div ).offset().top + $( div ).offset().left;
    
        if ( number !== originalnumber ) {
            // webfont is loaded and applied!
            clearInterval( interval );
        }
    }, 10 );
    

    【讨论】:

      【解决方案6】:

      我遇到了同样的问题。不知何故,我无法让 Google webfont loader 使用 ttf 字体(尤其是中文字体)或在加载字体时发送 jquery 响应。

      所以我想出了一个更基本的解决方案,在加载页面后动态更改字体时很有用。它显示正确加载字体的时间。

      首先我创建一个虚拟 div,然后用'abcd'填充它,然后给它一个字体大小 40,记录 div 的宽度。当通过按钮或任何东西调用“更改字体”事件时,它应该跟踪虚拟 div 宽度的变化。宽度变化代表字体发生了变化。

      HTML 代码

      <style>
          @font-face {
           font-family: 'font1';
           src:url('somefont.ttf')  format('truetype');
           }
      </style>
      <div id="dummy" style="border:1px solid #000; display:inline-block">abdc</div>
      
      <!--simple button to invoke the fontchange-->
      <input type="button" onclick="javascript:changefont('font1')" value="change the font"/>
      

      jQuery

      //create a variable to track initial width of default font
      var trackwidth
      
      //when change font is invoke
      function changefont(newfont)
      {
         //reset dummy font style
          $('#dummy').css('font-family','initial !important;');
          $('#dummy').css({'font-size':'40px'});
          $('#dummy').html('abcd');
      
          //ensure that trackwidth is only recorded once of the default font
          if(trackwidth==null)
          {
             trackwidth=( $('#dummy').width());
          }
      
          //apply new font
          $('#dummy').css('font-family',newfont);
          checkwidth()
      }
      
      function checkwidth()
      {
         //check if div width changed
         if($('#dummy').width() == trackwidth)
          {
              //if div never change, detect again every 500 milisecs
              setTimeout(checkwidth, 500);
          }
          else
          {
            //do something, font is loaded!
          }
      }
      

      【讨论】:

        【解决方案7】:

        我遇到了同样的问题,我正在尝试使用 readyfunction()、bind() 函数和我发现的其他一些函数,但它们都不起作用。最后我找到了一种解决方案,只需在加载动画之前应用一个延迟......就像这样:

        $(document).ready(function() {
        
        setTimeout(function (){
           // The animation
        },150);
        
        }); // end ready
        

        我知道这不是最好的解决方案,那么谁能告诉我一个更好的解决方案?

        谢谢!

        【讨论】:

        • @Fernando:请停止发布这种糟糕的编程技术
        猜你喜欢
        • 2012-08-31
        • 2010-11-22
        • 2013-01-15
        • 2018-01-11
        • 2016-12-24
        • 1970-01-01
        • 2016-10-21
        • 2019-06-02
        • 2011-10-14
        相关资源
        最近更新 更多