Back

Technologies:

javascriptjavascript
htmlhtml
csscss
avatar
Tolerim
a month ago

How can I implement a typewriter effect with JavaScript for dialogues?

In Entity.js, I have developed a dialogue system for the Entity class as shown below:

 
drawDialogue(context, element) {
     // To display dialogue box and face graphic
      context.drawImage(this.sprite.dialogueBox, 0, 90);
      context.drawImage(this.sprite.faceset, 6, 103);
      // Creating container and text element for dialogue
      const dialogueContainer = document.createElement('div');
      dialogueContainer.className = 'dialogue-container';
      const textElement = document.createElement('p');
      textElement.className = 'dialogue-text';
      textElement.innerText = this.text;
      dialogueContainer.appendChild(textElement);
      element.appendChild(dialogueContainer);
      // Creating container and text element for name
      const nameContainer = document.createElement('div');
      nameContainer.className = 'name-container';
      const nameElement = document.createElement('p');
      nameElement.innerText = this.displayName;
      nameElement.className = 'name-text';      
      nameContainer.appendChild(nameElement);
      element.appendChild(nameContainer);
    }
  }
Currently, I intend to add a typewriter effect to the textElement.innerText. However, I am not able to figure out how to add each letter to the dialogue text container one by one. The game loop method also updates the dialogue's state at a constant frame rate. As seen in the following block:

 
Loop() {
    const gameLoop = () => {
        // To check the interaction of any entity with the player
        Object.values(entities).forEach(entity => {
          //If an entity is interacting...
          if (entity.interacting) {
            // Display the dialogue
            entity.drawDialogue(this.context, this.element);
          }
        });
        // Requesting next frame
       requestAnimationFrame(gameLoop);
    };
    //Call the game loop method again
    gameLoop();
  }
As you can see, the function is called when the player interacts with an NPC. How can I efficiently add a typewriter effect to the dialogue system like Pokémon FireRed?

I have tried creating a separate class for typewriter text that prints each letter one by one, but I was not successful. Could you suggest any approaches to overcome this issue?

Answers(2)
avatar
Vogi
a month ago
Verified Answer
There are several ways to add a typewriter effect to your text. One way is to use JavaScript libraries such as TypewriterJSor typewriter-effect. Another way is to use CSS animations. You can also create your own typewriter effect using JavaScript. Here is an example of how you can create a typewriter effect using JavaScript:
function typeWriter(text, i, fnCallback) {
  if (i < (text.length)) {
    document.querySelector(".dialogue-text").innerHTML = text.substring(0, i+1) +'<span aria-hidden="true"></span>';
    setTimeout(function() {
      typeWriter(text, i + 1, fnCallback)
    }, 100);
  }
  else if (typeof fnCallback == 'function') {
    setTimeout(fnCallback, 700);
  }
}
You can call this function with the text you want to display and the speed at which you want the text to be typed out. Here is an example of how you can use this function:
const dialogueContainer = document.createElement('div');
dialogueContainer.className = 'dialogue-container';
const textElement = document.createElement('p');
textElement.className = 'dialogue-text';
dialogueContainer.appendChild(textElement);
element.appendChild(dialogueContainer);

const text = "This is an example of a typewriter effect.";
typeWriter(text, 0, function(){
  console.log("Typewriter effect complete.");
});
This will display the text one letter at a time in the dialogue box. I hope this helps! Let me know if you have any other questions.

Sources

Simple Typewriter Effect In Pure JavaScript – TypewriterJStypewriter-effect - npmTypewriter Effect | CSS-Tricks - CSS-TricksTypewriter Text Effect JavaScript — CodeHimHow To Create a Typing Effect - W3SchoolSimple Pure Javascript Typewriter Effect (Free Download) - Code Boxx
avatar
Tolerim
a month ago
To implement a typewriter effect on the textElement in your drawDialogue method, you can use a timeout function to append each letter to the element one by one. Here's an example implementation:
// Keep track of the index of the current letter being appended
let currentLetterIndex = 0;

// Create a function to append the next letter to the dialogue text
const appendNextLetter = () => {
  // Get the next letter to append
  const nextLetter = this.text.charAt(currentLetterIndex);

  // Append the letter to the dialogue text element
  textElement.innerText += nextLetter;

  // Increment the current letter index
  currentLetterIndex++;

  // If there are more letters to append, schedule the next append with a timeout
  if (currentLetterIndex < this.text.length) {
    setTimeout(appendNextLetter, 50);
  }
};

// Start the append process when the dialogue is first displayed
appendNextLetter();
This implementation uses a setTimeout function to append each letter to the innerText of the textElement one by one. The currentLetterIndex variable keeps track of the index of the current letter being appended, and the appendNextLetter function is called recursively with a 50 millisecond timeout until all of the letters have been appended. You'll need to make sure to remove the textElement.innerText = this.text; line, as the text will be appended one letter at a time instead of being set all at once.
;