在这篇博客中,我将向您解释如何在 VueJs 中制作打字动画。

这是一个预览:

[图像描述](https://res.cloudinary.com/practicaldev/image/fetch/s--jgvWRPfg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to- uploads.s3.amazonaws.com/uploads/articles/xbeyh1fwkc3p8jcjs52o.gif)

让我们开始吧...

创建一个新的 VueJs 项目。

$ 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

进入全屏模式 退出全屏模式

模板

模板非常简单。要创建打字机效果,您需要一个用于静态文本的元素和一个用于更改文本的元素。该组件包含三个封装在 div 中的 span 标签。

<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>

进入全屏模式 退出全屏模式

款式

我使用自己的自定义样式来显示内容和光标闪烁。这是代码,

<!-- 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>

进入全屏模式 退出全屏模式

InfoVueJs (默认 ([Vue 3] babel, eslint)) 组件中使用 SCSS,您可能会遇到 'sass-loader' 问题。请参阅此 博客以解决问题。

脚本

  • 数据

该组件主要包含 5 个值:typeValue、displayTextArray、typingSpeed、erasingSpeed 和 newTextDelay。 typeValue 字段是静态文本。 displayTextArray 字段是一个不断变化的单词数组。 typingSpeed 字段是打字速度,erasingSpeed 字段是删除速度。 newTextDelay 字段是开始打印下一个单词的延迟时间秒数。

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

进入全屏模式 退出全屏模式

方法

  • 类型文本()和擦除文本()

这些方法包含所有逻辑来确定正在键入哪个单词,是键入还是删除,或者根据“typeStatus”字段更改为下一个单词。看看下面。

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);
      }
    },
  },

进入全屏模式 退出全屏模式

创建的生命周期

当组件被加载时,它调用 typeText() 方法开始输入序列。

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

进入全屏模式 退出全屏模式

这是最终的代码:

<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>

进入全屏模式 退出全屏模式

你喜欢这个解决方案吗?不要忘记在GitHub上为 repo 加注星标。星星让我保持动力并受到高度赞赏。

欢迎代码审查。让我知道我是否可以做得更好。

Logo

前往低代码交流专区

更多推荐