vue 实现打字机效果

打字机效果组件,支持像打字机一样模仿键入文本。支持vue 插值语法和表格等打印

ps: 灵感来着于vue-type-writer 但是 这个组件过于简单 就自己整了一个

一、预览

在这里插入图片描述

二、代码

组件:

<template>
  <div :style="{ visibility: visibility }">
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: "vue-text-dot",
  props: {
    // 间隔时间
    interval: { type: Number, default: 75 },
    // 光标 建议有表格的时候不要使用光标 会导致渲染异常
    cursorStr: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      visibility: "hidden", // 
      timer: 0, // 定时器
      initialDom: null, // 记录初始dom
      progress: 0, // 当前文本书写进度
      // writeStatus: "NotStart",// 当前书写状态=> NotStart: 未开始;Processing:书写中;Completed 书写完毕
    };
  },
  mounted() {
    // 拷贝初始所有dom 便于重新开始
    this.initialDom = JSON.parse(JSON.stringify(this.$el.innerHTML));
  },
  methods: {
    // 开始 / 重新开始
    start() {
      this.visibility = "visible";
      this.progress = 0;
      this.$el.innerHTML = "";
      clearInterval(this.timer);
      this.write();
      this.$emit("writeStart");
    },
    // 暂停
    pause() {
      clearInterval(this.timer);
      this.$emit("writePause");
    },
    // 继续
    continueWrite() {
      if(!this.progress || this.progress >= this.initialDom.length){
        return
      }
      clearInterval(this.timer);
      this.write();
      this.$emit("writeContinue");
    },
    // 重置
    reset() {
      this.visibility = "hidden";
      this.progress = 0;
      this.$el.innerHTML = "";
      clearInterval(this.timer);
    },
    // 书写
    write() {
      this.timer = setInterval(() => {
        var current = this.initialDom.substr(this.progress, 1);
        // console.log(current);
        // 跳过 标签渲染
        if (current === "<") {
          this.progress = this.initialDom.indexOf(">", this.progress) + 1;
        } else {
          this.progress++;
        }
        // console.log(this.progress & 1, "this.progress");
        // 如果有光标配置 拼接到最新渲染的地方
        if (this.cursorStr) {
          this.$el.innerHTML =
            this.initialDom.substring(0, this.progress) +
            (this.progress < this.initialDom.length && this.progress & 1
              ? this.cursorStr
              : "");
        } else {
          this.$el.innerHTML = this.initialDom.substring(0, this.progress);
        }
        // 文本书写进度 大于需要书写的总长度 判断为渲染完成
        if (this.progress >= this.initialDom.length) {
          clearInterval(this.timer);
          this.$emit("writeEnd"); // 打字完成后的回调方法
        }
      }, this.interval);
    },
  },
  beforeDestroy() {
    clearInterval(this.timer);
  },
};
</script>

父级组件引用

<template>
  <div class="app-container home">
    <div class="body">
      <button type="primary" @click="start">开始 / 重新开始</button>
      <button type="primary" @click="pause">暂停</button>
      <button type="primary" @click="continueWrite">继续</button>
      <button type="primary" @click="reset">重置</button>
      <VueTypewriter
        class="tl"
        ref="typewriter"
        :interval="50"
        cursorStr=""
        @writeEnd="writeEnd"
      >
        <div class="comments">
          <p>const array = [1, 2, 2, 3, 4, 4, 5];</p>
          <p>const uniqueArray = Array.from(new Set(array));</p>
          <p>console.log(uniqueArray);</p>
          <p>{{ message }}</p>
        </div>
        <table>
          <tr>
            <td>1</td>
            <td>2</td>
            <td>3</td>
            <td>4</td>
            <td>5</td>
            <td>6</td>
            <td>7</td>
            <td>8</td>
            <td>9</td>
            <td>0</td>
          </tr>
        </table>
      </VueTypewriter>
    </div>
  </div>
</template>

<script>
import VueTypewriter from "./vue-typewriter";
export default {
  name: "Demo",
  components: { VueTypewriter },
  data() {
    return {
      message: "测试插值表达式 是否能够正常渲染",
    };
  },
  methods: {
    // 开始
    start() {
      this.$refs.typewriter.start();
    },
    // 暂停
    pause() {
      this.$refs.typewriter.pause();
    },
    // 继续
    continueWrite() {
      this.$refs.typewriter.continueWrite();
    },
    // 重置
    reset() {
      this.$refs.typewriter.reset();
    },
    // 结束回调
    writeEnd() {
      console.log("end");
    },
  },
};
</script>

<style scoped lang="scss">
.home {
  text-align: left;
  .body {
    width: 890px;
    height: 500px;
    padding: 20px;
    border: #b2c92a solid 10px;
    button {
      margin-right: 20px;
      padding: 8px 20px;
    }
    .comments {
      p {
        font-size: 18px;
        color: green;
      }
    }
    table {
      margin: 20px 0;
      border-collapse: collapse;
      td {
        padding: 10px 20px;
        border: 1px solid #ccc;
      }
    }
  }
}
</style>

### 使用 Typed.js 和 TypeIt 实现Vue.js 中的打字机效果 #### 使用 Typed.js 创建打字动画效果 为了在 Vue.js 项目中使用 Typed.js 来创建打字动画效果,首先需要安装该库。可以通过 npm 或 yarn 安装: ```bash npm install typed.js --save ``` 或者 ```bash yarn add typed.js ``` 接着,在组件内部引入并初始化 Typed.js: ```javascript <template> <div id="typed-text"></div> </template> <script> import { onMounted } from 'vue'; import Typed from 'typed.js'; export default { setup() { let typed; onMounted(() => { const options = { strings: ["First sentence.", "Second sentence."], typeSpeed: 40, backSpeed: 40, loop: true }; typed = new Typed('#typed-text', options); }); return {}; } }; </script> ``` 此代码片段展示了如何利用 `onMounted` 生命周期钩子函数来确保 DOM 已经加载完毕后再启动 Typed.js 动画[^1]。 #### 利用 TypeIt 插件实现更简洁的方式 对于寻求更加简便方法的人来说,TypeIt 提供了一种更为直观的方式来实现Vue.js 上的文字打字机效果。同样先要完成依赖项的安装工作: ```bash npm install @typeit/vue-next@latest --save ``` 随后按照如下方式定义组件结构与逻辑部分: ```html <template> <span v-type.it="{ speed: 50, cursor: false }"> Hello world! This is a message that will be typed out. </span> </template> <script> import { defineComponent } from 'vue'; import VTypeIt from '@typeit/vue-next'; export default defineComponent({ components: { VTypeIt }, }); </script> ``` 上述实例说明了怎样借助于自定义指令 `v-type.it` 轻松地将 TypeIt 集成到 Vue 组件之中,从而简化了配置过程并提高了可读性[^2]。 #### 结合 Spring Boot 和 Vue 构建复杂应用案例 如果目标是构建一个具有前后端分离架构的应用程序,并且想要加入类似 ChatGPT 的交互体验,则可以考虑参考基于 Spring Boot 和 Vue 技术栈所搭建的例子。这类解决方案不仅能够提供良好的视觉反馈给用户,还支持实时数据交换等功能特性[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值