如何知道一个字体(@ 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; } 

我怎么知道这些文件已经加载,我终于能够显示图标?

编辑:我不是说当页面加载(onload),因为字体可以加载整个页面之前。

现在在GitHub上: https : //github.com/patrickmarabeas/jQuery-FontSpy.js

本质上,该方法通过比较两种不同字体中string的宽度来工作。 我们使用Comic Sans作为testing对象的字体,因为它是Web安全字体中最不相同的字体,并且希望与您将要使用的任何自定义字体不同。 另外,我们正在使用非常大的字体大小,所以即使很小的差异也是显而易见的。 当Comic Sansstring的宽度已计算完毕后,font-family将更改为您的自定义字体,并回退到Comic Sans。 选中时,如果string元素宽度相同,则漫画Sans的后备字体仍在使用中。 如果没有,你的字体应该是可操作的。

我重写了字体负载检测的方法到一个jQuery插件,旨在让开发人员能够根据字体是否已加载样式元素。 已经添加了自动防故障定时器,所以如果自定义字体加载失败,用户不会没有内容。 这只是糟糕的可用性。

我还增加了对字体加载过程中发生的情况的更好的控制,并增加了对类的添加和删除的失败。 你现在可以做任何你喜欢的字体。 我只build议修改字体大小,行间距等,以尽可能接近自定义的字体,以便您的布局保持不变,用户可以获得预期的体验。

这是一个演示: 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兼容性删除,因为它不能正常工作,并遇到不同版本的问题。 哈克修复可以在这里find: https : //github.com/patrickmarabeas/jQuery-FontFaceSpy.js/issues/1

试试Google和Typekit开发的WebFont Loader ( github repo )。

这个例子首先以默认的serif字体显示文本; 那么在字体加载之后,它将以指定的字体显示文本。 (这段代码重现了Firefox在其他所有浏览器中的默认行为。)

这是从别人的解决scheme不同的方法。

我正在使用FontAwesome 4.1.0来构buildWebGL纹理。 这给了我一个想法,使用一个小的canvas渲染一个fa-square,然后检查该canvas中的一个像素以testing它是否已经加载:

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

因为它使用canvas,所以需要一个相当现代的浏览器,但是它也可以在IE8上使用polyfill。

这里有另一种方法来了解@ font-face是否已经被加载,而不必使用定时器:当精心devise的元素的大小被改变时,利用“滚动”事件来接收即时事件。

我写了一篇关于如何完成的博客文章 ,并在Github上发布了这个库 。

使用下面的代码:

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

这是另一种方法,至less可以确保加载font-awesome,而不是完整的OP解决scheme。 在wordpress论坛中find的原始代码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;} 

加载字体后,加载事件应该启动。