Animating three.js font from fontLoader()

I caught a bug when trying to deploy my site and the three.js canvas would not load (for some reason worked on dev but that’s neither here nor there) thanks to some very helpful individuals on this form.

The problem is that I am trying to animate text that was loaded using fontLoader.load(). For example, I add text to the scene using the following:

  (droidFont) => {
    const textGeometry = new TextGeometry('Scroll to Start', {
      size: 5,
      height: 1,
      font: droidFont,
      bevelSize: 5,
      bevelThickness: 2,
    const introTexture = new THREE.TextureLoader().load('suntexture.png');
    const textMaterial = new THREE.MeshBasicMaterial({map: introTexture, transparent:true, opacity: .5});
    cosnt introText = new THREE.Mesh(textGeometry, textMaterial);
    introText.position.set(-5, 37, -140);

Then, I want it to gently oscillate on the screen so as to not appear static, to do this I would include something like this in my animation function (called at the end of main.js):

function introAnimate() {
    introText.position.y += (Math.sin(clock.getElapsedTime())/62.8);
    introText.rotation.y += (Math.cos(clock.getElapsedTime())/700);

The problem with this is that the console (on dev/preview) says that introText is not defined, I’m assuming because it was declared in a function. I tried to fix this by first declaring them as var or const (didn’t work), then adding globalThis. or window. (ie window.introText). But the problem persists.

To be honest, I am surprised the npm run dev version ran correctly in the first place given this reference error. As now that I am tweaking it, main.js is behaving as expected (broken).

I have seen some versions of text animation using three.js flow, but I am interested in triggering certain animations on scroll, and doing some things to the font ‘object’ that I don’t think flow can do (ie position, rotation, opacity). Any suggestions on how to address this would be much appreciated.

Correct. I suggest you declare it as let introText; in a scope which is accessible for both the loader code and introAnimate(). Beside, change your animation code to:

if ( introText ) {

    introText.position.y += (Math.sin(clock.getElapsedTime())/62.8);
    introText.rotation.y += (Math.cos(clock.getElapsedTime())/700);


BTW: Don’t use var anymore. Stick to let and const.


Thanks for the tip and very good explanation - helped to resolve my problem swiftly.

Also had help from @drcmda on actually importing the font, the file path specified will not be included through npm run build.