Accessing font mesh outside of THREE.Fontloader?

0

I’ve got a scene setup and some text displayed using the font loader. It works pretty well and looks like this:

let blaster = loader.load(
  '/Assets/Fonts/Racing Sans One_Regular.json',
  function(font) {
    var geometry = new THREE.TextGeometry('BLASTER!', {
      font: font,
      size: 1.2,
      height: 0.5,
      curveSegments: 12,
    });
    var material = new THREE.MeshBasicMaterial();
    text = new THREE.Mesh(geometry, material);
    scene.add(text);
  },
);

However, I can’t figure out how to access text Mesh outside of this function. I want to be able to update the text’s coordinates and rotation after it’s been loaded in. Various methods have always thrown an error. Accessing any of the variables above returns undefined. Even using loader.onLoadComplete has no effect. Any clues?

Did you try logging the variable “text” after a long timeout to make sure it’s not because you access it before it’s loaded ?

Have you defined the variable text outside of the scope of the load function? If not, declare ‘text’ outside (before) the load() function and assign it’s value inside the scope of the loader function.

To expand on @Steven_Ophalvens’s anwser, you can do this

let text;

loader.load(
 '/Assets/Fonts/Racing Sans One_Regular.json',
 function(font) {
   var geometry = new THREE.TextGeometry('BLASTER!', {
     font: font,
     size: 1.2,
     height: 0.5,
     curveSegments: 12,
   });
   var material = new THREE.MeshBasicMaterial();
   text = new THREE.Mesh(geometry, material);
   scene.add(text);
 },
);

You can use text outside the onLoad function, however, you don’t know how long it will take for loading to finish so text will be undefined for a while. Make sure that you always check for the variable:

if( text !== undefined ) {
    // do something
}

This works fine in some cases, such as if you are getting user input and doing something with text, or using it in the animation loop. But if you need to access text immediately, you need to do it inside onLoad.

2 Likes

@Xavier_Gervais-Dumont use this code
let loader = new THREE.FontLoader()
font = loader.parse(jsonfile)
let geo = new THREE.TextGeometry(‘text’,{font: font, size: size})
let material = …
let mesh = …

Thank you all! It works using @Steven_Ophalvens and @looeee’s solutions. The problem was that the variable “text” was being accessed outside the scope of the function before the loader was done. Here is my solution in case anyone else has this problem:

let starText;

var loader = new THREE.FontLoader();

let star= loader.load("/Assets/Fonts/Racing Sans One_Regular.json", function(font) {
  var geometry = new THREE.TextGeometry("STAR", {
    font: font,
    size: 1.3,
    height: 0.5,
    curveSegments: 12
  });
  starText = new THREE.Mesh(geometry, material);
  scene.add(starText);
});


let waitForLoad = () => {
  if (blasterText === undefined) {
    window.requestAnimationFrame(waitForLoad);
  } else {
    scene.add(starText);
  }
};

EDIT: Is there any way I can use the font loader just once, make sure the font is loaded, then use that font when I need to create new text elements? Thanks!

@Xavier_Gervais-Dumont I did not test this, but I think that if you declare your font variable at the same time as the text variable, and assign it the value ‘font’ inside the loader, it will be available afterwards. Like @looeee said, test that variable before you use it, as the loader might not yet have finished and your fontvariable can still be null or unasigned.

Ok so here is the weirdest thing. At first I did this:

let RacingOne;
loader.load("/Assets/Fonts/Racing Sans One_Regular.json", function(font) {
  RacingOne = font;
});
let params = {
  font: RacingOne,
  size: 1.3,
  height: 0.5,
  curveSegments: 12
};

So far so good. I have a splash screen on my game which gives the browser enough time to execute the loader. RacingOne is assigned to the font. However, when I’m actually creating the mesh a few seconds later, the font is defined in the code above but undefined where I’m calling the new THREE.TextGeometry.

  generate3D = () => {
    let blaster = new THREE.TextGeometry("BLASTER!", params);
    blaster.translate(-3.8, 0.25, -0.25);
    blasterText = new THREE.Mesh(blaster, material);
    scene.add(blasterText);
  };

If I open dev tools and pause the program, I can see that RacingOne IS defined but undefined when being called as part of the object params. What gives?!

What happens if you try it like this :

let RacingOne, params, blasterText;
loader.load("/Assets/Fonts/Racing Sans One_Regular.json", function(font) {
 RacingOne = font;
 params = {
   font: RacingOne,
   size: 1.3,
   height: 0.5,
   curveSegments: 12
 };
});
  generate3D = () => {
    if(!params) {
        return;
    }
    let blaster = new THREE.TextGeometry("BLASTER!", params);
    blaster.translate(-3.8, 0.25, -0.25);
    blasterText = new THREE.Mesh(blaster, material);
    scene.add(blasterText);
  };

I assume that you only call generate3D when the loader has finished, but still, I added a small check for params.

Sorry for any typo’s, typed on my smarpthone.

It works! Thank you for taking the time! I very much appreciate it!

1 Like