簡體   English   中英

如何知道字體(@font-face)是否已經加載?

[英]How to know if a font (@font-face) has already been loaded?

我正在使用 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)時說話,因為字體可以在整個頁面之前加載。

現在在 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

試試由 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。

其實,有一個很好的方法來理解所有字體是否開始下載或加載完全或是否會陷入一些錯誤,但不僅僅是針對特定字體,請注意以下代碼:

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

這是另一種無需使用計時器即可了解 @font-face 是否已加載的方法:當精心設計的元素的大小發生更改時,利用“滾動”事件接收瞬時事件。

我寫了一篇關於它是如何完成的博客文章,並在 Github 上發布了該

嘗試類似的東西

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

然后做

#text {visibility: hidden;}
#text.shown {visibility: visible;}

load 事件應該在字體加載后觸發。

或者,您可以將font-display: block添加到 @font-face 聲明中。

這會指示瀏覽器在加載字體之前將后備字體呈現為不可見,無需display: none或任何 javascript 加載字體檢測

Typescript、Angular 的解決方案。

如果您正在使用 Angular,您可以使用此模塊進行字體檢查。 這是我如何做到的。

// document.fonts.check extension
import type {} from 'css-font-loading-module';

ngOnInit() {
  this.onFontLoad();
}

public onFontLoad() {
  let myTimer = setInterval(() => {
    if (document.fonts.check('14px MyFont')) {
      console.log('Font is loaded!');
      clearInterval(myTimer);
    } else {
      console.log('Font is loading');
    }
  }, 1);
}

您可以在加載字體時添加加載屏幕,並在加載字體時移除加載屏幕。 確保使用計時器並根據您的需要更改它。 希望能幫助到你!

這是一種替代方法,至少可以確保加載 font-awesome,而不是OP 的完整解決方案。 在此處https://wordpress.stackexchange.com/a/165358/40636的 wordpress 論壇中找到的原始代碼。

它是不可知的,可以與任何字體樣式資源一起使用,例如 font-awesome 可以檢查字體系列。 再多考慮一下,我敢打賭這可以應用於更多……

<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<script>
    (function($){
        var faSpan = $('<span class="fa" style="display:none"></span>').appendTo('body');
        if (faSpan .css('fontFamily') !== 'FontAwesome' ) {
            // Fallback Link
            $('head').append('<link href="/css/font-awesome.min.css" rel="stylesheet">');
        }
        faSpan.remove();
    })(jQuery);
</script>

使用以下代碼:

<!DOCTYPE HTML>
<html>
    <head>
    </head>

<body>
<canvas id="canvasFont" width="40px" height="40px" style="position: absolute; display: none;"></canvas>

<script>
function IsLoadedFonts()
    {
        var Args = arguments;
        var obj = document.getElementById('canvasFont');
        var ctx = obj.getContext("2d");
        var baseFont = (/chrome/i.test(navigator.userAgent))?'tims new roman':'arial';
         //................
          function getImg(fon)
          { 
            ctx.clearRect(0, 0, (obj).width, (obj).height);
            ctx.fillStyle = 'rgba(0,0,0,1.0)';
            ctx.fillRect( 0, 0, 40, 40 );
            ctx.font = '20px '+ fon;
            ctx.textBaseline = "top";
            ctx.fillStyle = 'rgba(255,255,255,1.0)';
            ctx.fillText( '\u0630', 18, 5 );
            return ctx.getImageData( 0, 0, 40, 40 );
          };
        //..............
          for(var i1=0; i1<Args.length; i1++)
          {
            data1 = getImg(Args[i1]);
            data2 = getImg(baseFont);
            var isLoaded = false;
            //...........
            for (var i=0; i<data1.data.length; i++)
            {
                if(data1.data[i] != data2.data[i])
                    {isLoaded = true; break;}
            }
            //..........
            if(!isLoaded)
                    return false;
         }
         return true;
    };

     setTimeout(function(){alert(IsLoadedFonts('myfont'));},100);
   </script>
   </body>

可以檢查多種字體:

setTimeout(function(){alert(IsLoadedFonts('font1','font2','font3'));},100);

以下代碼僅適用於歌劇,但很簡單:

if(!document.defaultView.getComputedStyle(document.getElementById('mydiv'))['fontFamily'].match(/myfont/i))
          alert("font do not loaded ");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM