フォント(@ font-face)がすでにロードされているかどうかを知る方法は?


80

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

これらのファイルがロードされ、最終的にアイコンを表示できるようになったことをどのように確認できますか?

編集: フォントはページ全体の前にロードされる可能性があるため、ページがロードされるとき(オンロード)は話していません。


うまくいけば、我々はネイティブのフォントのイベントを持つことができ、すぐにblog.typekit.com/2013/02/05/more-reliable-font-events
Pacerier


2
この質問は重複しており、元の質問に対する2015年の更新回答を投稿しました。
ダンダスカレスク2015

ソリューションの用途がありますスクロール検出smnh.me/web-font-loading-detection-without-timersは
Pacerier

回答:


44

現在GitHubにあります:https//github.com/patrickmarabeas/jQuery-FontSpy.js

基本的に、この方法は2つの異なるフォントの文字列の幅を比較することで機能します。Comic Sansは、Webセーフフォントの中で最も異なり、使用するカスタムフォントとは十分に異なるため、テスト対象のフォントとして使用しています。さらに、非常に大きなフォントサイズを使用しているため、わずかな違いでも明らかになります。Comic Sans文字列の幅が計算されると、font-familyはカスタムフォントに変更され、ComicSansにフォールバックします。チェックすると、文字列要素の幅が同じ場合、ComicSansの代替フォントが引き続き使用されます。そうでない場合は、フォントが機能しているはずです。

フォントの読み込みを検出する方法を、フォントが読み込まれたかどうかに基づいて要素のスタイルを設定できるように設計された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の互換性は、正しく機能せず、異なるバージョンで問題が発生したため削除されました。ハッキーな修正はここで見つけることができます:https//github.com/patrickmarabeas/jQuery-FontFaceSpy.js/issues/1


フォントの長さを比較しています...これはWebFontLoader(他の回答を参照)も行っていることですか?
Pacerier 2016

1
そしてとにかく、キャラクターを比較する 多くの「コピー」フォントは同じ長さになるように設計されているため長さのは多くのフォントでは機能しません。たとえば、Arial、Helvetica、およびLiberation Sansはすべて、すべての文字に対して同じ文字幅を持っています。en.wikipedia.org/wiki/Arialも参照してください。これまでのところ、キャンバスを使用したピクセルごとのチェックが唯一の
確実

1
これを使用して、フォントが読み込まれる前にiScrollが要素のサイズを間違って計算する際に発生していた問題を修正する必要がありました。しかし、私はjQueryを使用していないので、バニラjsバージョンを作成しました:github.com/keithswright/vanilla-fontspyは私のために働いているようです。
キース

@ Pacerier-異なる長さを持つ必要があるのは、選択したテストと選択した読み込みフォントだけであることに注意してください。したがって、Comic Sansに同じ文字幅のフォントがたくさんある場合を除いて、ほとんどの場合、これは機能するはずです。
BryanGrezeszak 2016

20

GoogleとTypekitによって開発されたWebFontLoadergithub repo)をお試しください。

この例では、最初にデフォルトのセリフフォントでテキストを表示します。次に、フォントがロードされた後、指定されたフォントでテキストが表示されます。(このコードは、他のすべての最新ブラウザーでのFirefoxのデフォルトの動作を再現しています。)


9

これは、他のソリューションとは異なるソリューションへのアプローチです。

FontAwesome4.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でもポリフィルを使用して機能する可能性があります。


KonvaJSでfont-awesomeをロードするときに同じ問題に直面しています
Mahdi Alkhatib 2016

4

実際には、すべてのフォントが完全にダウンロードまたはロードされ始めてエラーに陥るかどうかを理解するための良い方法がありますが、それは特定のフォントだけのものではありません。次のコードに注意してください。

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

ありがとうございました。それは完全に機能します!しかし、そのフォントを使用する<span>要素をどこかに配置して、フォントの読み込みをトリガーする必要があります。
tyt2y3

残念ながら、まだのWindows ServerとバンドルされていIE11でサポートされていない
ガイパッシー

@ GuyPassy、IE11とは何なのかわかりません!!
AmerllicA

4
私は一日とても幸運かもしれたい@AmerllicA
ガイ・パッシー

3

タイマーをまったく使用せずに@ font-faceがすでに読み込まれているかどうかを知る別の方法は、「スクロール」イベントを利用して、慎重に作成された要素のサイズが変更されたときに瞬時のイベントを受信することです。

私はそれがどのように行われるかについてブログ投稿を書き、Githubでライブラリを公開しました。


0

次のようなものを試してください

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

そしてします

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

フォントがロードされた後、loadイベントが発生するはずです。


これは、$(function(){...})ページ全体がロードされたときに実行されるものと同じです。
Shankar Cabus 2012

1
それは同じではありません。hayk.martの例は、ページ内のDOM(HTML)ANDアセット(CSS、JS、画像、フレーム)の読み込みが完了するとトリガーされます。DOMのみの読み込みが完了したときの例。
ブレイズ

この回答が却下された理由に興味がある場合は、クイック検索で正しいアプローチであることがわかります

-1

これは、少なくとも、そのフォント-awesomeがロードされ、保証されます別のアプローチである、NOT OPへの完全なソリューションを。こちらのワードプレスフォーラムにある元のコードhttps://wordpress.stackexchange.com/a/165358/40636

これは不可知論的であり、font-familyをチェックできる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="https://stackoverflow.com/css/font-awesome.min.css" rel="stylesheet">');
        }
        faSpan.remove();
    })(jQuery);
</script>

これは、Font-Awesomeがロードされない場合(またはロードが遅すぎる場合)のフォールバックですが、フォントのロードが終了したときに通知しません。
ダンダスカレスク2015

@DanDascalescu回答を更新して、これが完全なソリューションではなく、font-awesomeライブラリがロードされることを保証するだけの代替アプローチであることをより明確に示しました。前のイテレーションからいくつかの反対票を獲得したので、うまくいけば、それは少しそれをクリアします。
oucil 2016年

-3

以下のコードを使用してください。

<!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 ");

Leeftが1年前に投稿したのと同じ「キャンバスにレンダリング」のアイデア。
ダンダスカレスク2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.