[Vuejs]-Typewriter animation using Vue Js

0๐Ÿ‘

โœ…

I found the way to make it work.
The following code is updated and works using Vue.js 3.

<script setup>
import { ref } from "vue";

const phrases = [
  "I am John Doe.",
  "I am student.",
  "I am developer.",
];

const currentPhraseIndex = ref(0);
const currentCharacterIndex = ref(0);
const currentPhrase = ref("");
const isDeleting = ref(false);

function loop() {
  const currentPhraseText = phrases[currentPhraseIndex.value];

  if (!isDeleting.value) {
    currentPhrase.value += currentPhraseText[currentCharacterIndex.value];
    currentCharacterIndex.value++;
  } else {
    currentPhrase.value = currentPhrase.value.slice(0, -1);
    currentCharacterIndex.value--;
  }

  if (currentCharacterIndex.value === currentPhraseText.length) {
    isDeleting.value = true;
  }

  if (currentCharacterIndex.value === 0) {
    currentPhrase.value = "";
    isDeleting.value = false;
    currentPhraseIndex.value++;
    if (currentPhraseIndex.value === phrases.length) {
      currentPhraseIndex.value = 0;
    }
  }

  const spedUp = Math.random() * (80 - 50) + 50;
  const normalSpeed = Math.random() * (300 - 200) + 200;
  const time = isDeleting.value ? spedUp : normalSpeed;
  setTimeout(loop, time);
}

loop();
</script>
<template>
    <div>
      <h1 id="title">{{ currentPhrase }}</h1>
    </div>
</template>
๐Ÿ‘คGarfaz

1๐Ÿ‘

Try to put variables in data property and function in methods, or i composition api make variables reactive:

const { ref, reactive, onMounted } = Vue
const app = Vue.createApp({
  setup() {
    const opt = reactive({
      currentPhraseIndex: 0, 
      currentCharacterIndex: 0, 
      currentPhrase: "", 
      isDeleting: false
    })
    const phrases = reactive([
      "I'm John Doe",
      "I'm student",
      "I'm developer"
    ])
    const text = ref('')
    const loop = () => {
      const currentPhraseText = phrases[opt.currentPhraseIndex];
      if (!opt.isDeleting) {
        opt.currentPhrase += currentPhraseText[opt.currentCharacterIndex];
        opt.currentCharacterIndex++;
      } else {
        opt.currentPhrase = opt.currentPhrase.slice(0, -1);
        opt.currentCharacterIndex--;
      }
      text.value = opt.currentPhrase;
      if (opt.currentCharacterIndex === currentPhraseText.length) {
        opt.isDeleting = true;
      }
      if (opt.currentCharacterIndex === 0) {
        opt.currentPhrase = "";
        opt.isDeleting = false;
        opt.currentPhraseIndex++;
        if (opt.currentPhraseIndex === opt.phrases?.length) {
          opt.currentPhraseIndex = 0;
        }
      }
      const spedUp = Math.random() * (80 - 50) + 50;
      const normalSpeed = Math.random() * (300 - 200) + 200;
      const time = opt.isDeleting ? spedUp : normalSpeed;
      setTimeout(loop, time);
    }
    onMounted(() => {
      loop()
    })
    return {
      text
    }
  }
})
app.mount('#demo')
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="demo">
  <h2>{{ text }}</h2>
</div>

0๐Ÿ‘

You have to add this line

if (opt.currentCharacterIndex === currentPhraseText.length) {
  opt.isDeleting = true;
  opt.currentPhraseIndex = 0; //  <===== you have to add this line 
}
๐Ÿ‘คRagnar Lapin

Leave a comment