글꼴 (@ 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;
}

이러한 파일이로드되었고 마침내 아이콘을 표시 할 수 있는지 어떻게 알 수 있습니까?

편집 : 글꼴이 전체 페이지보다 먼저로드 될 수 있기 때문에 페이지가로드 될 때 (onload) 말하는 것이 아닙니다.


곧 네이티브 글꼴 이벤트를 가질 수 있기를 바랍니다. blog.typekit.com/2013/02/05/more-reliable-font-events
Pacerier


2
이 질문은 중복 되며 원래 질문에 2015 년 업데이트 답변 을 게시했습니다 .
Dan Dascalescu

솔루션 사용에있어 스크롤 감지 에서 smnh.me/web-font-loading-detection-without-timers은
Pacerier

답변:


44

이제 GitHub에서 : https://github.com/patrickmarabeas/jQuery-FontSpy.js

기본적으로이 방법은 서로 다른 두 글꼴의 문자열 너비를 비교하여 작동합니다. 우리는 Comic Sans를 테스트 할 글꼴로 사용하고 있습니다. 웹 안전 글꼴 중 가장 다르고 사용할 사용자 정의 글꼴과는 충분히 다르기 때문입니다. 또한 우리는 매우 큰 글꼴 크기를 사용하므로 작은 차이도 분명합니다. Comic Sans 문자열의 너비가 계산되면 글꼴 모음이 Comic Sans로 대체되는 사용자 지정 글꼴로 변경됩니다. 선택하면 문자열 요소 너비가 동일하면 Comic Sans의 대체 글꼴이 계속 사용됩니다. 그렇지 않은 경우 글꼴이 작동합니다.

글꼴로드 감지 방법을 개발자에게 글꼴로드 여부에 따라 요소 스타일을 지정할 수있는 기능을 제공하도록 설계된 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


글꼴 길이 비교 ... 이것이 WebFont Loader (다른 답변 참조)도 수행하는 일입니까?
Pacerier

1
어떤 경우에도 많은 "복사"글꼴이 동일한 길이 를 갖도록 설계 되었기 때문에 문자 길이 비교 는 많은 글꼴에서 작동하지 않습니다 . 예를 들어 Arial, Helvetica 및 Liberation Sans는 모두 모든 문자에 대해 동일한 문자 너비를 갖습니다. en.wikipedia.org/wiki/Arial 도 참조하십시오 . 지금까지이 ..... 유일한 바보 방지 옵션이 될 수 있습니다 캔버스를 사용하여 픽셀 단위 검사처럼 보인다
Pacerier

1
글꼴이로드되기 전에 iScroll에서 요소의 크기를 잘못 계산하는 문제를 해결하기 위해 이것을 사용해야했습니다. 그러나 나는 jQuery를 사용하지 않으므로 바닐라 js 버전을 만들었습니다. github.com/keithswright/vanilla-fontspy 가 나를 위해 일하는 것 같습니다.
Keith

@Pacerier-다른 길이를 가져야하는 것은 선택한 테스트와 선택한 로딩 글꼴뿐입니다. 따라서 Comic Sans에 동일한 문자 너비를 가진 많은 글꼴이 있지 않는 한 대부분의 경우 여전히 작동합니다.
BryanGrezeszak

20

시도 WebFont 로더 ( GitHub의의의 repo 구글과 Typekit에서 개발을).

이 예제는 먼저 기본 serif 글꼴로 텍스트를 표시합니다. 그런 다음 글꼴이로드 된 후 지정된 글꼴로 텍스트를 표시합니다. (이 코드는 다른 모든 최신 브라우저에서 Firefox의 기본 동작을 재현합니다.)


9

여기에 다른 솔루션과 다른 접근 방식이 있습니다.

WebGL 텍스처를 빌드하기 위해 FontAwesome 4.1.0을 사용하고 있습니다. 그래서 작은 캔버스를 사용하여 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

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

IE11에서는 지원되지 않습니다. 아쉽게도 여전히 Windows Server에 번들로 제공됩니다
Guy Passy

@GuyPassy, ​​IE11이 뭔지 모르겠어요 !!
AmerllicA

4
@AmerllicA 언젠가 운이 좋으면 좋겠어요
Guy Passy

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) 및 자산 (CSS, JS, 이미지, 프레임)로드가 완료되면 트리거됩니다. DOM 만로드가 완료된 경우의 예입니다.
Blaise

이 답변이 반대 투표 된

-1

이것은 적어도 그 글꼴 최고로드, 보장합니다 다른 접근 방식이다 NOT 영업에 대한 완벽한 솔루션을. 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이로드되지 않는 경우 (또는 너무 느리게로드되는 경우! ) 대비책 이지만 글꼴로드가 완료 되면 알리지 않습니다 .
Dan Dascalescu

@DanDascalescu 나는 이것이 완전한 솔루션이 아닌 글꼴 멋진 라이브러리가로드되도록 보장하는 대체 접근 방식임을 더 명확하게 나타 내기 위해 답변을 업데이트했습니다. 내가 이전 반복에서 약간의 반대표를 얻었 기 때문에 그것이 약간 정리되기를 바랍니다.
oucil

-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 년 전에 게시 한 것과 동일한 "캔버스로 렌더링"아이디어 .
Dan Dascalescu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.