Как узнать, если шрифт (@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 71

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

});

снимите этот Фук!

.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, не комплексное решение для ФП. Оригинальный код нашел на форумах вот вордпресс 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 ");