Как узнать, был ли уже загружен шрифт (@font-face)?

Я использую 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;
}

Как узнать, что эти файлы были загружены, и я, наконец, могу показать значки?

Edit: Я не говорю, когда страница загружена (onload), потому что шрифт может быть загружен до всей страницы.

7 ответов


Теперь на GitHub:https://github.com/patrickmarabeas/jQuery-FontSpy.js

по сути метод работает путем сравнения ширины строки в двух разных шрифтов. Мы используем Comic Sans в качестве шрифта для тестирования, потому что это самые разные веб-безопасные шрифты и, надеюсь, достаточно разные для любого пользовательского шрифта, который вы будете использовать. Кроме того, мы используем очень большой размер шрифта, поэтому даже небольшие различия будут очевидны. При ширине комикс Строка Sans была вычислена, семейство шрифтов изменено на ваш пользовательский шрифт с резервным вариантом для Comic Sans. Если ширина строкового элемента одинакова, то резервный шрифт Comic Sans по-прежнему используется. Если нет, шрифт должен работать.

я переписал метод обнаружения загрузки шрифта в плагин jQuery, предназначенный для предоставления разработчику возможности стилизовать элементы на основе того, был ли загружен шрифт или нет. Таймер fail safe был добавлен, поэтому пользователь не остается без содержимого, если пользовательский шрифт не загружается. Это просто плохое удобство использования.

Я также добавил больший контроль над тем, что происходит во время загрузки шрифта и при сбое с включением добавления и удаления классов. Теперь вы можете делать с купелью все, что хотите. Я бы рекомендовал только изменить размер шрифтов, межстрочный интервал и т. д., Чтобы ваш обратный шрифт был как можно ближе к пользовательскому, чтобы ваш макет оставался нетронутым, а пользователи получали ожидаемый опыт.

вот демо:http://patrickmarabeas.github.io/jQuery-FontSpy.js

бросьте следующее В a .JS файл и ссылаться на него.

(function($) {

    $.fontSpy = function( element, conf ) {
        var $element = $(element);
        var defaults = {
            font: $element.css("font-family"),
            onLoad: '',
            onFail: '',
            testFont: 'Comic Sans MS',
            testString: '[email protected]',
            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'
    });

});

удалить МНПК!

.hideMe {
    visibility: hidden !important;
}

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

EDIT: FontAwesome совместимость удалена, поскольку она не работала должным образом и столкнулась с проблемами с разными версиями. В игре может быть найден здесь: https://github.com/patrickmarabeas/jQuery-FontFaceSpy.js/issues/1


попробовать Загрузчик WebFont (GitHub РЕПО), разработанный Google и Typekit.

сначала отображается текст в шрифте с засечками по умолчанию; затем после загрузки шрифтов отображается текст в указанном шрифте. (Этот код воспроизводит поведение Firefox по умолчанию во всех современных браузерах.)


здесь другой подход к решениям от других.

Я использую FontAwesome 4.1.0 для создания текстур WebGL. Это дало мне идею использовать крошечный холст для рендеринга FA-квадрата, а затем проверить пиксель в этом холсте, чтобы проверить, загружен ли он:

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.


вот еще один способ узнать, был ли @font-face уже загружен без использования таймеров вообще: используйте событие "прокрутки", чтобы получить мгновенное событие, когда размер тщательно созданного элемента изменяется.

Я написал блоге о том, как это делается и опубликовали библиотека на Github.


Это альтернативный подход, который, по крайней мере, гарантирует, что font-awesome загружен,не полное решение для OP. Оригинальный код найден на форумах wordpress здесь https://wordpress.stackexchange.com/a/165358/40636.

это агностик и будет работать с любым ресурсом стиля шрифта, таким как 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>

попробуйте что-то вроде

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

и затем сделать

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

событие load должно срабатывать после загрузки шрифтов.


используйте приведенный ниже код:

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

приведенный ниже код работает только в opera, но легко:

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