skip to Main Content

I am trying to create a typewriter effect using javascript, I want to write the first sentence first, then second sentence and so on.

I tried doing it using using setTimeout and it is working fine, but I want to add more sentences and do it using generators to add more sentences, but I am having really hard time to figure it out and translate my code to generator function because setTimeouts are nested and are in loops.

This is my code using setTimeout:

const s1 = `I am sentence 1`;
const s2 = `I am sentence 2`;

s1.split('').forEach((ch, i) => {
  setTimeout(c => {
    document.querySelector('h1').textContent += c
  }, i * 70, ch)
});
setTimeout(() => {
  s2.split('').forEach((ch, i) => {
    setTimeout(c => {
      document.querySelector('h2').textContent += c
    }, i * 100, ch)
  });
}, s1.length * 70)
<h1></h1>
<h2></h2>

Please help me doing it using generator, thank you!

2

Answers


  1. I’d not do it with a generator, but create a promise wrapper for setTimeout and place the code in an async method. This way you can write your code like it was synchronous (but of course it isn’t)

    function delay(ms){ 
      return new Promise(res => setTimeout(res, ms));
    }
    
    async function typewriter() {
      let sentences = ["...", "...", ...]
    
      for (let s of sentences){
        let e = document.querySelector(...); //find the correct element 
        for (let c of s){
          e.textContent += c;
          await delay(50); //wait after each character
        }
    
        await delay(100); // wait between sentences 
      }
    }
    

    This is just the basics. Don’t know how you will find the respective DOM element for each sentence. I just assumed you have some way and the elements will exit ( thus this code will throw an error if it doesn’t)

    Login or Signup to reply.
  2. The implementation using generator may look like this:

    function* generator(str) {
        yield* str;
    }
    
    const addSentence = (element, sentence, done) => {
      const gen = generator(sentence);
      const el = document.querySelector(element);
      const interval = setInterval(() => {
        const ch = gen.next().value;
        if (!ch) {
          clearInterval(interval);
          if (done) {
            done();
          }
          return;
        }
        el.textContent += ch;
      }, 100);
    }
    addSentence('h1', 'Sentence 1', () => {
      addSentence('h2', 'Sentence 2');
    }); 
    <h1></h1>
    <h2></h2>

    Please let me know if this helps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search