How to add a Typewriter animation in VueJs

In this blog, I’m going to explain to you how to make a typing animation in VueJs.

Here’s a preview:

Let’s get started…

Create a new VueJs project.

$ vue create animations-vuejs

Vue CLI v5.0.4
? Please pick a preset: Default ([Vue 3] babel, …


This content originally appeared on DEV Community and was authored by Gayathri R

In this blog, I'm going to explain to you how to make a typing animation in VueJs.

Here's a preview:

Image description

Let's get started...

Create a new VueJs project.

$ vue create animations-vuejs

Vue CLI v5.0.4
? Please pick a preset: Default ([Vue 3] babel, eslint)


Vue CLI v5.0.4
✨  Creating project in /home/user/tutorials/animations-vuejs.
🗃  Initializing git repository...
⚙️  Installing CLI plugins. This might take a while...


added 839 packages, and audited 840 packages in 35s

84 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
🚀  Invoking generators...
📦  Installing additional dependencies...


added 97 packages, and audited 937 packages in 9s

94 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
⚓  Running completion hooks...

📄  Generating README.md...

🎉  Successfully created project animations-vuejs.
👉  Get started with the following commands:

 $ cd animations-vuejs
 $ npm run serve

Template

The template is quite simple. To create the typewriter effect, you need an element for static text and an element for changing text. This component contains three span tags encapsulated in a div.

<template>
  <div class="container">
    <h1>
      Hi, I'm a
      <span class="typed-text">{{ typeValue }}</span>
      <span class="blinking-cursor">|</span>
      <span class="cursor" :class="{ typing: typeStatus }">&nbsp;</span>
    </h1>
  </div>
</template>

Styles

I've used my own custom styling for displaying the contents & cursor blinking. Here is the code,

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss" scoped>
.container {
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}
h1 {
  font-size: 6rem;
  font-weight: normal;
  span.typed-text {
    color: #d2b94b;
  }
}

// Cursor blinking CSS Starts...
.blinking-cursor {
  font-size: 6rem;
  color: #2c3e50;
  -webkit-animation: 1s blink step-end infinite;
  -moz-animation: 1s blink step-end infinite;
  -ms-animation: 1s blink step-end infinite;
  -o-animation: 1s blink step-end infinite;
  animation: 1s blink step-end infinite;
}
@keyframes blink {
  from,
  to {
    color: transparent;
  }
  50% {
    color: #2c3e50;
  }
}
@-moz-keyframes blink {
  from,
  to {
    color: transparent;
  }
  50% {
    color: #2c3e50;
  }
}
@-webkit-keyframes blink {
  from,
  to {
    color: transparent;
  }
  50% {
    color: #2c3e50;
  }
}
@-ms-keyframes blink {
  from,
  to {
    color: transparent;
  }
  50% {
    color: #2c3e50;
  }
}
@-o-keyframes blink {
  from,
  to {
    color: transparent;
  }
  50% {
    color: #2c3e50;
  }
}
// Cursor blinking CSS Ends...
</style>

Info Using SCSS inside the VueJs (Default ([Vue 3] babel, eslint)) components you may face 'sass-loader' issues. Please refer to this blog for fixing the problem.

Script

  • Data

This component mainly contain 5 values: typeValue, displayTextArray, typingSpeed, erasingSpeed, and newTextDelay. The typeValue field is the static text. The displayTextArray field is an array of changing words. The typingSpeed field is the typing speed, and the erasingSpeed field is the delete speed. The newTextDelay field is the delay time seconds to start printing the next word.

data: () => {
    return {
      typeValue: "",
      typeStatus: false,
      displayTextArray: ["YouTuber", "Developer", "Blogger", "Designer", "Freelancer"],
      typingSpeed: 100,
      erasingSpeed: 100,
      newTextDelay: 2000,
      displayTextArrayIndex: 0,
      charIndex: 0,
    };
  },

Methods

  • typeText() & eraseText()

These methods contain all the logic to determine which word is being typed, whether to type or delete, or to change to the next word based on the 'typeStatus' field. Take a look below.

methods: {
    typeText() {
      if (this.charIndex < this.displayTextArray[this.displayTextArrayIndex].length) {
        if (!this.typeStatus) this.typeStatus = true;
        this.typeValue += this.displayTextArray[this.displayTextArrayIndex].charAt(
          this.charIndex
        );
        this.charIndex += 1;
        setTimeout(this.typeText, this.typingSpeed);
      } else {
        this.typeStatus = false;
        setTimeout(this.eraseText, this.newTextDelay);
      }
    },
    eraseText() {
      if (this.charIndex > 0) {
        if (!this.typeStatus) this.typeStatus = true;
        this.typeValue = this.displayTextArray[this.displayTextArrayIndex].substring(
          0,
          this.charIndex - 1
        );
        this.charIndex -= 1;
        setTimeout(this.eraseText, this.erasingSpeed);
      } else {
        this.typeStatus = false;
        this.displayTextArrayIndex += 1;
        if (this.displayTextArrayIndex >= this.displayTextArray.length)
          this.displayTextArrayIndex = 0;
        setTimeout(this.typeText, this.typingSpeed + 1000);
      }
    },
  },

Created Lifecycle

When the component is loaded, it calls the typeText() method to begin the typing sequence.

created() {
   setTimeout(this.typeText, this.newTextDelay + 200);
},

Here's the final code:

<template>
  <div class="container">
    <h1>
      Hi, I'm a
      <span class="typed-text">{{ typeValue }}</span>
      <span class="blinking-cursor">|</span>
      <span class="cursor" :class="{ typing: typeStatus }">&nbsp;</span>
    </h1>
  </div>
</template>

<script>
export default {
  name: "typeWiriter",
  data: () => {
    return {
      typeValue: "",
      typeStatus: false,
      displayTextArray: ["YouTuber", "Developer", "Blogger", "Designer", "Freelancer"],
      typingSpeed: 100,
      erasingSpeed: 100,
      newTextDelay: 2000,
      displayTextArrayIndex: 0,
      charIndex: 0,
    };
  },
  props: {},
  created() {
    setTimeout(this.typeText, this.newTextDelay + 200);
  },
  methods: {
    typeText() {
      if (this.charIndex < this.displayTextArray[this.displayTextArrayIndex].length) {
        if (!this.typeStatus) this.typeStatus = true;
        this.typeValue += this.displayTextArray[this.displayTextArrayIndex].charAt(
          this.charIndex
        );
        this.charIndex += 1;
        setTimeout(this.typeText, this.typingSpeed);
      } else {
        this.typeStatus = false;
        setTimeout(this.eraseText, this.newTextDelay);
      }
    },
    eraseText() {
      if (this.charIndex > 0) {
        if (!this.typeStatus) this.typeStatus = true;
        this.typeValue = this.displayTextArray[this.displayTextArrayIndex].substring(
          0,
          this.charIndex - 1
        );
        this.charIndex -= 1;
        setTimeout(this.eraseText, this.erasingSpeed);
      } else {
        this.typeStatus = false;
        this.displayTextArrayIndex += 1;
        if (this.displayTextArrayIndex >= this.displayTextArray.length)
          this.displayTextArrayIndex = 0;
        setTimeout(this.typeText, this.typingSpeed + 1000);
      }
    },
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss" scoped>
.container {
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}
h1 {
  font-size: 6rem;
  font-weight: normal;
  span.typed-text {
    color: #d2b94b;
  }
}

// Cursor blinking CSS Starts...
.blinking-cursor {
  font-size: 6rem;
  color: #2c3e50;
  -webkit-animation: 1s blink step-end infinite;
  -moz-animation: 1s blink step-end infinite;
  -ms-animation: 1s blink step-end infinite;
  -o-animation: 1s blink step-end infinite;
  animation: 1s blink step-end infinite;
}
@keyframes blink {
  from,
  to {
    color: transparent;
  }
  50% {
    color: #2c3e50;
  }
}
@-moz-keyframes blink {
  from,
  to {
    color: transparent;
  }
  50% {
    color: #2c3e50;
  }
}
@-webkit-keyframes blink {
  from,
  to {
    color: transparent;
  }
  50% {
    color: #2c3e50;
  }
}
@-ms-keyframes blink {
  from,
  to {
    color: transparent;
  }
  50% {
    color: #2c3e50;
  }
}
@-o-keyframes blink {
  from,
  to {
    color: transparent;
  }
  50% {
    color: #2c3e50;
  }
}
// Cursor blinking CSS Ends...
</style>

Do you like this solution? Don’t forget to star the repo on GitHub. Stars keep me motivated and are highly appreciated.

Code reviews welcome. Let me know if I can do something better.


This content originally appeared on DEV Community and was authored by Gayathri R


Print Share Comment Cite Upload Translate Updates
APA

Gayathri R | Sciencx (2022-04-23T15:20:58+00:00) How to add a Typewriter animation in VueJs. Retrieved from https://www.scien.cx/2022/04/23/how-to-add-a-typewriter-animation-in-vuejs/

MLA
" » How to add a Typewriter animation in VueJs." Gayathri R | Sciencx - Saturday April 23, 2022, https://www.scien.cx/2022/04/23/how-to-add-a-typewriter-animation-in-vuejs/
HARVARD
Gayathri R | Sciencx Saturday April 23, 2022 » How to add a Typewriter animation in VueJs., viewed ,<https://www.scien.cx/2022/04/23/how-to-add-a-typewriter-animation-in-vuejs/>
VANCOUVER
Gayathri R | Sciencx - » How to add a Typewriter animation in VueJs. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/04/23/how-to-add-a-typewriter-animation-in-vuejs/
CHICAGO
" » How to add a Typewriter animation in VueJs." Gayathri R | Sciencx - Accessed . https://www.scien.cx/2022/04/23/how-to-add-a-typewriter-animation-in-vuejs/
IEEE
" » How to add a Typewriter animation in VueJs." Gayathri R | Sciencx [Online]. Available: https://www.scien.cx/2022/04/23/how-to-add-a-typewriter-animation-in-vuejs/. [Accessed: ]
rf:citation
» How to add a Typewriter animation in VueJs | Gayathri R | Sciencx | https://www.scien.cx/2022/04/23/how-to-add-a-typewriter-animation-in-vuejs/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.