vue打字机效果
一、问题引入
AI流行,做一个智能问答的需求
二、解决办法
- 流式接口响应;
- 使用插件typeit;
- 纯代码实现;
三、代码实现
本文着重纯代码实现打字机效果,话不多说,代码如下
1.封装VueTypewriter组件
<!-- * @Description: * @Author: * @version: 1.0 * @Date: * @LastEditors: * @LastEditTime: --> <template> <div :style="{ visibility: visibility }"> <slot></slot> </div> </template> <script> export default { name: "VueTypewriter", 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); // console.log(this.initialDom.substring(0, this.progress)); } this.$emit("writeTyping"); // 文本书写进度 大于需要书写的总长度 判断为渲染完成 if (this.progress >= this.initialDom.length) { clearInterval(this.timer); this.$emit("writeEnd"); // 打字完成后的回调方法 } }, this.interval); }, }, beforeDestroy() { clearInterval(this.timer); }, }; </script>
2.组件使用
<VueTypewriter ref="typewriter" :interval="50" cursorStr="" @writeEnd="writeEnd(i)" @writeTyping="writeTyping"> <div>{{ v.answer }}</div> </VueTypewriter>
四、示例
代码:
<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>
效果如下:

参考来源:https://blog.csdn.net/weixin_46544600/article/details/144085811

浙公网安备 33010602011771号