Jak sprawdzić, czy czcionka (@font-face) została już załadowana?

Używam Font-Awesome, ale podczas gdy pliki czcionek nie są ładowane, ikony pojawiają się z klawiszem.

Chcę, aby te ikony miały display:none, gdy pliki nie są ładowane.

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

Skąd mam wiedzieć, że te pliki zostały załadowane i w końcu mogę pokazać ikony?

Edit: Nie mówię o załadowaniu strony (onload), ponieważ czcionka może być załadowana przed całą stroną.

Author: Patrick, 2012-09-07

7 answers

Teraz na Githubie: https://github.com/patrickmarabeas/jQuery-FontSpy.js

Zasadniczo metoda działa poprzez porównanie szerokości ciągu znaków w dwóch różnych czcionkach. Używamy Comic Sans jako czcionki do testowania, ponieważ jest to najbardziej różna z bezpiecznych czcionek internetowych i mam nadzieję, że wystarczająco różna od każdej niestandardowej czcionki, której będziesz używać. Dodatkowo używamy bardzo dużej wielkości czcionki, więc nawet małe różnice będą widoczne. Gdy szerokość Komiksu bez sznurka została obliczona, rodzina czcionek została zmieniona na niestandardową czcionkę, z powrotem do Comic Sans. Gdy zaznaczone, jeśli Szerokość elementu string jest taka sama, czcionka zapasowa Comic Sans jest nadal używana. Jeśli nie, czcionka powinna działać.

Przepisałem metodę wykrywania ładowania czcionek do wtyczki jQuery zaprojektowanej, aby dać programiście możliwość stylowania elementów w oparciu o to, czy czcionka została załadowana, czy nie. Dodano wyłącznik czasowy, aby użytkownik nie został bez zawartości, jeśli niestandardowa czcionka nie zostanie załadowana. To po prostu zła użyteczność.

Dodałem również większą kontrolę nad tym, co dzieje się podczas ładowania czcionek i na fail z włączeniem dodawania i usuwania klas. Teraz możesz zrobić, co chcesz z czcionką. Polecam tylko modyfikację rozmiaru czcionek, odstępów między wierszami itp., Aby uzyskać czcionkę jak najbardziej zbliżoną do niestandardowej, aby układ pozostał nienaruszony, a użytkownicy uzyskali oczekiwane wrażenia.

Oto demo: http://patrickmarabeas.github.io/jQuery-FontSpy.js

Wrzuć następujące do a .plik js i odwołaj się do niego.

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

Zastosuj go do swojego projektu

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

});

Usuń tego FOUCA!

.hideMe {
    visibility: hidden !important;
}

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

EDIT: usunięto kompatybilność FontAwesome, ponieważ nie działała poprawnie i napotkała problemy z różnymi wersjami. Hacky fix można znaleźć tutaj: https://github.com/patrickmarabeas/jQuery-FontFaceSpy.js/issues/1

 42
Author: Patrick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-12 05:35:40

Try WebFont Loader (github repo), opracowany przez Google i Typekit.

Ten przykład najpierw wyświetla tekst w domyślnej czcionce, a następnie po załadowaniu czcionek wyświetla tekst w określonej czcionce. (Ten kod odtwarza domyślne zachowanie Firefoksa we wszystkich innych nowoczesnych przeglądarkach.)

 17
Author: cassi.lup,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-20 02:35:41

Oto inne podejście do rozwiązań od innych.

Używam FontAwesome 4.1.0 do budowania tekstur WebGL. To dało mi pomysł, aby użyć malutkiego płótna do renderowania FA-kwadratu, a następnie sprawdzić piksel w tym płótnie, aby sprawdzić, czy się załadował: {]}

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

Ponieważ używa canvas, wymaga dość nowoczesnej przeglądarki, ale może działać również na IE8 z polyfill.

 9
Author: Leeft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-07 19:41:50

Oto inny sposób na sprawdzenie, czy plik @font-face został już załadowany bez konieczności używania timerów: użyj zdarzenia "scroll", aby otrzymać natychmiastowe zdarzenie, gdy rozmiar starannie wykonanego elementu zostanie zmieniony.

Napisałem post na blogu o tym, jak to się robi i opublikowałem bibliotekę na Githubie.

 3
Author: smnh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-29 22:53:05

Jest to alternatywne podejście, które przynajmniej zapewni, że font-awesome zostanie załadowany, a nie kompletne rozwiązanie do OP. oryginalny kod znaleziony na forach wordpress tutaj https://wordpress.stackexchange.com/a/165358/40636 .

Jest agnostyczny i będzie działał z dowolnym zasobem stylu czcionki, takim jak font-awesome, gdzie można sprawdzić rodzinę czcionek. Z trochę więcej myśli założę się, że można to zastosować do znacznie więcej...

<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>
 -1
Author: oucil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-13 12:37:28

Spróbuj czegoś takiego

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

And then do

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

Zdarzenie load powinno zostać wywołane po załadowaniu czcionek.

 -2
Author: hayk.mart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-07 05:50:42

Użyj poniższego kodu:

<!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>

Można sprawdzić wiele czcionek:

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

Poniższy kod działa tylko w operze, ale jest łatwy:

if(!document.defaultView.getComputedStyle(document.getElementById('mydiv'))['fontFamily'].match(/myfont/i))
          alert("font do not loaded ");
 -2
Author: ali bagheri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-21 10:28:53