skip to Main Content

So I’ve been playing around with a project that includes a random quote generator, and I was hoping to combine it with a simple typewriter-esque animation when the generator loads a new quote.

Problem is I know very little about javascript and basically have no idea what I’m doing, which makes it hard to implement other people’s similar-but-not-quite-it solutions.

The basics of the code is this;

const generateQuote = function() {
  const quotes = [{
      quote: "Here's a text",
    },
    {
      quote: "Here's another one",
    },
    {
      quote: "Lorem ipsum bla bla",
    },
    {
      quote: "I can do this all day",
    }
  ];

  let arrayIndex = Math.floor(Math.random() * quotes.length);
  document.getElementById("quotetxt").innerHTML = quotes[arrayIndex].quote;
}

window.onload = function loadquote() {
  generateQuote();
  document.getElementById("generate").addEventListener('click', generateQuote);
}
<p id="quotetxt"> </p>
<button id="generate">generate</button>

I’ve tried combining it with scripts for typewriter effects I’ve seen around (like the basic one on W3schools), but I can’t figure out how to make it work like I want. I can make the initially loaded quote appear with the animation, or animate single texts, but not from a random array on button press like I want.

At one point I managed to somehow make the quote generator scramble all the letters in the quotes, though I have no idea how I did that and I didn’t keep the code.

I’ve seen some jquery stuff around for typewriter effects, but they all seem far more advanced than what I’m looking for, but if there’s a simple one you could recommend that would be fine too.

(I’m also completely new to stackoverflow, I did my best to follow the guidelines but I apologise if I missed something)

3

Answers


  1. Here is the simplest I could think of

    Note I have changed some of the code layout. For example there is no need to create the quote array every time the generateQuote is called.
    I also clear the existing quote if the button is clicked mid quote.
    I put the typewriter function inside the load event handler since it needs the textElement to be in scope. I could get the textElement each time inside the function if I wanted to move the function outside the load event handler, but this is a simple script so I stayed pragmatic.

    const quotes = [
      { quote: "Here's a text" },
      { quote: "Here's another one" },
      { quote: "Lorem ipsum bla bla" },
      { quote: "I can do this all day" }
    ];
    
    
    const generateQuote = () => {
      let arrayIndex = Math.floor(Math.random() * quotes.length);
      return quotes[arrayIndex].quote;
    }
    
    window.addEventListener('DOMContentLoaded', () => {
      const textElement = document.getElementById('quotetxt');
      let tId; // timeout handle
      // Typewriter function
      const typeWriter = (text, i = 0) => {
        if (i < text.length) { // while the counter is less than the length of the string
          textElement.innerHTML = text.substring(0, i + 1); // show next letter
          // call the function with the counter at the next letter
          tId = setTimeout(() => typeWriter(text, i + 1), 100); // Adjust speed by changing timeout
        }
      };
    
      // Event listener for button
      document.getElementById('generate').addEventListener('click', (e) => {
        clearTimeout(tId); // kill running typewriting
        textElement.textContent = "";
        typeWriter(generateQuote());
      });
      typeWriter(generateQuote()); // initialise
    });
    <p id="quotetxt"> </p>
    <button id="generate">generate</button>
    Login or Signup to reply.
  2. Here’s a modified version of this CodePen

    Added to include the typewriter effect, you will have to reset the innerHTML (as this does) in order to get the effect again when pressing the button.

    const generateQuote = function() {
      const quotes = [{
          quote: "Here's a text",
        },
        {
          quote: "Here's another one",
        },
        {
          quote: "Lorem ipsum bla bla",
        },
        {
          quote: "I can do this all day",
        }
      ];
    
      let arrayIndex = Math.floor(Math.random() * quotes.length);
      document.getElementById("quotetxt").innerHTML = `<p  class="line-1 anim-typewriter">${quotes[arrayIndex].quote}</p>`;
    }
    
    window.onload = function loadquote() {
      generateQuote();
      document.getElementById("generate").addEventListener('click', generateQuote);
    }
    /* Google Fonts */
    
    @import url(https://fonts.googleapis.com/css?family=Anonymous+Pro);
    
    /* Global */
    
    html {
      min-height: 100%;
      overflow: hidden;
    }
    
    body {
      height: calc(100vh - 8em);
      padding: 4em;
      color: rgba(255, 255, 255, .75);
      font-family: 'Anonymous Pro', monospace;
      background-color: rgb(25, 25, 25);
    }
    
    .line-1 {
      position: relative;
      top: 50%;
      width: 24em;
      margin: 0 auto;
      border-right: 2px solid rgba(255, 255, 255, .75);
      font-size: 180%;
      text-align: center;
      white-space: nowrap;
      overflow: hidden;
      transform: translateY(-50%);
    }
    
    
    /* Animation */
    
    .anim-typewriter {
      animation: typewriter 4s steps(44) 1s 1 normal both, blinkTextCursor 500ms steps(44) infinite normal;
    }
    
    @keyframes typewriter {
      from {
        width: 0;
      }
      to {
        width: 24em;
      }
    }
    
    @keyframes blinkTextCursor {
      from {
        border-right-color: rgba(255, 255, 255, .75);
      }
      to {
        border-right-color: transparent;
      }
    }
    <div id="quotetxt"></div>
    <button id="generate">generate</button>
    Login or Signup to reply.
  3. I add simple code below.

        var timeId;
    const generateQuote = function () {
      const quotes = [
        {
          quote: "Here's a text",
        },
        {
          quote: "Here's another one",
        },
        {
          quote: "Lorem ipsum bla bla",
        },
        {
          quote: "I can do this all day",
        },
      ];
    
      let arrayIndex = Math.floor(Math.random() * quotes.length);
      var i = 0;
      var txt = quotes[arrayIndex].quote; /* The text */
      var speed = 100; /* The speed/duration of the effect in milliseconds */
      clearInterval(timeId);
      document.getElementById("quotetxt").innerHTML = "";
      function typeWriter() {
        if (i < txt.length) {
          document.getElementById("quotetxt").innerHTML += txt.charAt(i);
          i++;
          timeId = setTimeout(typeWriter, speed);
        }
      }
      typeWriter();
    };
    
    window.onload = function loadquote() {
      generateQuote();
      document
        .getElementById("generate")
        .addEventListener("click", generateQuote);
    };
     <p id="quotetxt"></p>
        <button id="generate">generate</button>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search