Jump to content

How to make sure that a font is loaded?


Sebi
 Share

Recommended Posts

Hi guys,

 

I have encountered a really weird behaviour with webfonts and am looking for a good way to solve this issue.

I programmed 2 functions to check if the font was loaded.

 

@css/main.css

@font-face {	font-family: 'GraphicPixel';	src: url('../fonts/graphicpixel-webfont.eot');	src: url('../fonts/graphicpixel-webfont.eot?#iefix') format('embedded-opentype'),		 url('../fonts/graphicpixel-webfont.woff') format('woff'),		 url('../fonts/graphicpixel-webfont.ttf') format('truetype'),		 url('../fonts/graphicpixel-webfont.svg#GraphicPixelRegular') format('svg');	font-weight: normal;	font-style: normal;}

@js/util.js

// web font loaded - might want to change that// css solution ....function WebFontLoaded(fonts, callback) {	if(!(fonts instanceof Array)) {		fonts = [fonts];	}	var random = "giItT1WQy@!-/#", // random characters that usually differ in width depending on the font		loader = [];    for(var i = 0; i < fonts.length; i++) {		var span = $('<span>').text(random).css({			"font-family": "sans-serif",			"font-variant": "normal",			"font-style": "normal",			"font-weight": "normal",			"font-size": "50px",			"letter-spacing": "0",			"position": "absolute",			"left": "-2000px",			"top": "-2000px"		}).appendTo('body');		loader.push([span, span.outerWidth()]);		span.css("font-family", fonts[i]);    }	var interval = setInterval(function() {		var count = 0;		for(var i = 0; i < loader.length; i++) {			if(loader[i][0].outerWidth() != loader[i][1]) {				count++;			}		}		if(count == loader.length) {			clearInterval(interval);			for(var i = 0; i < loader.length; i++) {				loader[i][0].remove();			}			callback();		}	}, 50);};

So I create a span with a text in sans-serif, then I change the font and check all 50ms if the offset width has changed, if so -> new font has been loaded.

 

@js/renderer.js

// webfont loaded ... might need to change that?fontLoaded: function(font, callback) {	var check = new PIXI.Text("giItT1WQy@!-/#", { font: "50px MissingFontForPixi" });	var width = check.width;	var interval = setInterval(function() {			            check.setStyle({ font: "50px " + font });	    check.updateText();	    if(check.width != width) {	        clearInterval(interval);	        check.destroy(true);		callback();	    }	}, 50);}

Here I create a textchild with an non-existend font and then I keep upating that textchild. If the width changed (then the font has been loaded)

 

Is there any better way to check if a font has been loaded without having to add any huge apis to my app?

Link to comment
Share on other sites

Hi xerver,

 

I will take a look at those later, but all links I click have a different solution, was looking for something more standard, more reliable.

 

There isn't a "Standard" way that I know of, just read up about the problem and try a couple different solutions until you find one you are happy with.

Link to comment
Share on other sites

There isn't a "Standard" way that I know of, just read up about the problem and try a couple different solutions until you find one you are happy with.

 

And that is the sad part. I expect my browser to know when a font is ready, since it has to render the font as it is loaded and I don't see why the browser could not report back to me about the readystate. But I believe that is not the right place to discuss that issue.

 

I have adjusted my own method and hope that it will work properly on all devices.

Thanks anyway.

Link to comment
Share on other sites

I've also been struggling with this and have read everything on the subject, just like you have.

My last hope is that someone will post something incredibly clever in this thread.

Any takers ... ?

Until then, the only reliable way to load fonts seems to be bitmap texture atlases and Google's web font loader:

 

https://github.com/typekit/webfontloader

 

... a huge hulking API for something that should be really simple :(

 

UPDATE: I found something pretty useful! Font.js:

 

http://pomax.nihongoresources.com/pages/Font.js/

Link to comment
Share on other sites

  • 1 year later...

Found this thread while searching for a solution ... 

 

The solution I settled for is to use the webfont in the markup (could be an invisible tag, for example inside a <noscript> tag.)

That way the browser makes sure the webfont is loaded before rendering the page, which is also before the canvas stuff begins. Not optimal if you want a more streaming experience, but in my case the webfont is used on the first screen of the game so works for me. 

 

Hope this could be helpful to someone in the future.

Link to comment
Share on other sites

Webfontloader is a small library that normalises font loading across platform and across provider. Just install from npm or include in the page, it will then accept a callback or I think it even returns a promise now too so it's a quick and simple solution that solves your problem explicitly, I'm not really sure why it's not job done.

Font.js isn't really designed for what you're after a polling the width of a span sounds crazy but it is exactly what webfontloader does on most platforms.

Webfontloader will, by default, append classes to your HTML tag, so you can use those to hide content if you don't mind the page loading, or you can use a mutation observer to respond when the class changes (overly complex when the library exposes both a callback and a promise).

I think it even has a synchronous mode, stuff in the head blocks the page so whack it in there and the browser won't do much until your fonts are ready.

But, seriously, use the lib and use the callback. Load other stuff while the font is loading then crack on with the rest of your app/game/whatever

Link to comment
Share on other sites

  • 1 year later...
  • 1 year later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...