Jump to content

How to check if a font has been fully loaded into the PIXI.Text object?


MrBill
 Share

Recommended Posts

I've noticed a small visual bug with the menu I have. When I startup the game for the first time in the browser (in a private window with no cookies), the "label" objects have their fonts properly display but the "button" objects do not. The buttons appear to display the default font instead.

image.thumb.png.d47c293111f07eba72fe27169b0e3dd0.png

However, once I have refreshed the page at least once, all fonts display properly for every subsequent refresh.

image.thumb.png.fe88b0cb6c732a85c4b5773a46873750.png

So this has me thinking that the font is not loading into the button object fast enough before it's drawn the first time and I'm wondering how I can fix that.

Here's some relevant code:

This function is responsible for creating the PIXI.Text for my custom label class.

Renderer.prototype.setLabelGraphic = function(label){
  let message = label.text;
  let style = this.textStyles[label.textStyle];
  let text = new PIXI.Text(message, style);
  label.graphic = text;
};

This function is responsible for creating the PIXI.Text and Rectangle for my custom button class.

Renderer.prototype.setButtonGraphic = function(button){
  let minimumWidth = 150;
  let minimumHeight = 50;
  let container = new PIXI.Container();

  // Create label component.
  let message = button.text;
  let textStyle = this.textStyles[button.textStyle];
  let text = new PIXI.Text(message, textStyle);

  // Create button component.
  let rectangle = this.configureButtonRect(button.style);
  let rectangleWidth = (text.width < minimumWidth) ? minimumWidth : text.width;
  let rectangleHeight = (text.height < minimumHeight) ? minimumHeight: text.height;
  rectangle.drawRect(0, 0, rectangleWidth, rectangleHeight);
  rectangle.endFill();

  // Center text within containing rectangle.
  let center = [(rectangleWidth / 2) - (text.width / 2), (rectangleHeight / 2) - (text.height / 2)]
  text.position.set(center[0], center[1]);

  // Combine them into the container.
  container.addChild(rectangle);
  container.addChild(text);

  button.graphic = container;
};

The configureButtonRect in the previous:

Renderer.prototype.configureButtonRect = function(buttonStyle){
  let rectangle = new PIXI.Graphics();
  let colour;
  if(buttonStyle === "default"){
    colour = 0xFFBF75;
    rectangle.lineStyle(2, 0xCA826C, 1);
  } else console.error(`Error configuring button rectangle: {buttonStyle} is not a valid button style.`);
  rectangle.beginFill(colour);
  return rectangle;
};

Drawing of either object is simply add their respective graphic attribute to the stage. I feel that the solution is to simply just have the game wait for the fonts load before adding to the container via promises or callbacks, but I'm not exactly sure which part of the code would be responsible for the delay.

Link to comment
Share on other sites

during your loading phaze, you can do something like this, is how i load my fonts.
is vanilla without libs, or you have some great libs on npm for less code.

return new Promise((resolve, rej) => {
                    const fontsList = [
                        new FontFace('ArchitectsDaughter', 'url(fonts/ArchitectsDaughter.ttf)', { style: 'normal', weight: 700 } ),
                        new FontFace('zBirdyGame', 'url(fonts/zBirdyGame.ttf)',{ style: 'normal', weight: 700 }),
                        new FontFace('Flux_Architect_Regular', 'url(fonts/Flux_Architect_Regular.ttf)',{ style: 'normal', weight: 700 }),
                        new FontFace('ampersand', 'url(fonts/ampersand.ttf)',{ style: 'normal', weight: 700 }),
                        new FontFace('ShadowsIntoLight', 'url(fonts/ShadowsIntoLight.ttf)',{ style: 'normal', weight: 700 }),
                    ];
                    fontsList.forEach(fonts => {
                        fonts.load().then(function(loadedFontFace) {
                            document.fonts.add(loadedFontFace);
                            //document.body.style.fontFamily = '"Junction Regular", Arial';
                        });
                    });
                    document.fonts.ready.then(()=>{ resolve() });
                })

 

Edited by jonforum
Link to comment
Share on other sites

4 minutes ago, themoonrat said:

I recommend using https://github.com/bramstein/fontfaceobserver to load custom fonts before creating pixi text objects

I actually already have implemented fontfaceobserver after my previous thread a month earlier when I asked about custom fonts. To me, It wouldn't make sense for the Labels to work and the Buttons to not in the same session if they use the same font. I'll post my code for that too though just in case im wrong:

Engine.prototype.loadAllFonts = function(callback){
  allFonts = this.assets.get(this.fontsKey);
  allFonts = allFonts.map(font => new FontFaceObserver(font).load());
  Promise.all(allFonts).then(callback);
};

Where allFonts is an object based on this .json file:

{
  "customFonts": [
    "Bitmgothic"
  ]
}

When I have time I'll take a look at the code example jonforum posted to see if I can implement a fix.

Link to comment
Share on other sites

26 minutes ago, MrBill said:

I actually already have implemented fontfaceobserver after my previous thread a month earlier when I asked about custom fonts. To me, It wouldn't make sense for the Labels to work and the Buttons to not in the same session if they use the same font. I'll post my code for that too though just in case im wrong:


Engine.prototype.loadAllFonts = function(callback){
  allFonts = this.assets.get(this.fontsKey);
  allFonts = allFonts.map(font => new FontFaceObserver(font).load());
  Promise.all(allFonts).then(callback);
};

i think your code missing document.fonts.add(loadedFontFace);  document.fonts.ready.then(()=>{ resolve() });

but am not pro on this subject, i remember nothing.

 

Edited by jonforum
Link to comment
Share on other sites

 

1 hour ago, MrBill said:

To me, It wouldn't make sense for the Labels to work and the Buttons to not in the same session if they use the same font

The thing with custom fonts, is that, once loaded, the first instance being used doesn't work, but after that it does.

So if you're creating text before ffo is finished, or during it finishing, then I'd totally expect to see it not working on text drawn at one time compared to text created / drawn at another time.

If you want to 'force' text to redraw, call updateText on it. But that's a brute force method rather than solving the underlying issue.

Link to comment
Share on other sites

  • 2 months later...

More than 2 months later and I decide to take another look at the function. I think I found a fix. This is what the function looks like now

Engine.prototype.loadAllFonts = function(callback){
  allFonts = this.assets.get(this.fontsKey);
  allFonts = allFonts.map(font => new FontFaceObserver(font).load());
  Promise.all(allFonts).then(callback());
};

I changed

Promise.all(allFonts).then(callback)

to

Promise.all(allFonts).then(callback())

Basically I didn't explictly have the callback function execute in .then(). I stumbled upon this by accident as I was trying to debug the contents of allFonts. Such a dumb mistake in hindsight :P. Thanks everyone for the help.

Edited by MrBill
Link to comment
Share on other sites

I spoke too soon. That wasn't the source of the problem. The .then() in either code snippets seems to execute the callback just fine. The REAL problem was simply that I would create the menus (and PIXI.Text objects) before I even STARTED loading the fonts. So it's still a dumb mistake but a much more higher level one completely on me 😐.

Anyways I got the problem fixed. It was an absolute pain in the ass to debug though because pressing F12 to check the debug console could cause enough of a delay for fonts to load in time, giving the illusion that the problem was fixed when it wasn't.

Still, appreciate the help. Hopefully I won't have to post again in this thread.

Link to comment
Share on other sites

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...