3

So I was making a simple text animation and decided to make it so once its done, you can restart it. Problem being, im not sure of a way to force it to restart onclick once done. The way im doing it, it can and will restart in the middle if you click the screen, which is fine, but it continues to print some text from before. Anyway heres my code

<html>
    <head>
        <title>Page Title</title>
    </head>
    <body>
    <h1 id=typing-style></h1>
    <script>
    var i=0,text="Mitchell";
        setInterval(()=>{
            document.getElementById("typing-style").innerHTML += text.charAt(i);
            i++;
        },300)
        
function rerun() {
  document.getElementById("typing-style").innerHTML = " ";
  var i=0,text="Mitchell";
        setInterval(()=>{
            document.getElementById("typing-style").innerHTML += text.charAt(i);
            i++;
        },300)
}
        </script>
        <canvas id="screen" onclick="rerun()" width=1000% height=1000%></canvas>
    </body>
</html>

So what I've been trying to do is get it to be able to restart when you click the screen, but stop the current process. Hope someone can figure it out.

3 Answers3

2

This code never calls clearInterval, so both timers will run at the same time, cross-talking each other's text manipulations. The code is repeated unnecessarily--it's easier to write it once in a function, then call the function each time you need to run the logic.

For this sort of thing, I'd create a closure that encapsulates the data needed to create a timer: an interval and index. You can return a timer start function that handles resetting timer state and can be invoked in an event listener (preferred to onclick because it keeps behavior out of the markup; read more).

Lastly, prefer textContent or innerText to innerHTML. They're faster, safer and more semantically appropriate if the content is purely text-based.

const makeTextTyper = (el, text, speed) => {
  let i;
  let interval;  
  return () => {
    clearInterval(interval);
    el.innerText = "";
    i = 0;
    interval = setInterval(() => {
      if (i < text.length) {
        el.innerText += text[i++];
      }
      else {
        clearInterval(interval);
      }
    }, speed)
  };
};

const buttonEl = document.querySelector("button");
const typerEl = document.querySelector("h3");
const runTyper = makeTextTyper(typerEl, "Mitchell", 300);
buttonEl.addEventListener("click", runTyper);
runTyper();
<button>restart</button>
<h3></h3>
ggorlen
  • 44,755
  • 7
  • 76
  • 106
0

When the rerun function is invoked the existing interval needs to be cancelled, this can be achieved using the clearInterval method.

<!DOCTYPE html>
<html>
<head>
    <title>Page Title</title>
</head>
<body>
    <h1 id="typing-style"></h1>
    <script>
            var i = 0, text = "Mitchell";
            var interval;
            
            interval = setInterval(()=>{
              document.getElementById("typing-style").innerHTML += text.charAt(i);
              i++;
            },300)
              
            function rerun() {
              clearInterval(interval);
              document.getElementById("typing-style").innerHTML = " ";
              var i=0,text="Mitchell";
              interval = setInterval(()=>{
                document.getElementById("typing-style").innerHTML += text.charAt(i);
                i++;
              },300)
            }
    </script>
    <canvas height="1000%" id="screen" onclick="rerun()" width="1000%"></canvas>
</body>
</html>
slx
  • 1
0

I would write a if statement inside the rerun function to determine whether the animation is done or not. You can determine whether the text is done by using the .length method.

   var typingText = document.getElementById("typing-style")
   if(typingText.length === 8) //length of Mitchell {
  document.getElementById("typing-style").innerHTML = " ";
  var i=0,text="Mitchell";
     setInterval(()=>{
         document.getElementById("typing-style").innerHTML += text.charAt(i);
         i++;
     }
     },300)
     } ```


Love2Code
  • 440
  • 6
  • 19