阅读量:3
打字机效果组件,支持像打字机一样模仿键入文本。支持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>