效果展示:
组件代码:
<template>
<view class="type-writer-container">
<text>{{ contentText }}</text>
<text v-show="initPosition !== contentText.length" :style="{ display: initPosition % 2 == 0 || initPosition == total ? 'hidden' : 'inline-block' }">|</text>
</view>
</template>
<script>
export default {
name: 'type-writer',
props: {
contentList: {
type: Array,
required: true
},
delaytime: {
type: Number,
default: 100
},
uid: {
type: String | Number
}
},
data() {
return {
timer: null,
contentText: '',
initPosition: 0,
total: 0
};
},
watch: {
contentList(newvalue) {
const me = this;
clearInterval(me.timer);
me.timer = null;
me.initWriter(newvalue);
}
},
mounted() {
const me = this;
console.log(me);
me.initWriter(me.contentList);
},
methods: {
initWriter(messageList) {
const me = this;
const text = messageList.join('');
// me.initPosition =;
me.total = text.length;
me.getChatContent(text);
},
// 逐字显示内容,text:全部聊天内容
getChatContent(text) {
const me = this;
// 定义当前定时器
let timer = setInterval(() => {
me.initPosition++;
// 判断是否全部拼接
if (me.initPosition == me.total) {
console.log(' me.total', me.total);
// 拼接内容
let nowStr = text.substring(0, me.initPosition);
me.contentText = nowStr;
// 重置起始值
// me.initPosition = 0;
// 拼接完成清除定时器
clearInterval(me.timer);
me.$emit('finish', me.uid, true);
return;
}
// 未拼接完成的取字符串子串进行拼接更新
let nowStr = text.substring(0, me.initPosition);
me.contentText = nowStr;
}, 200);
me.timer = timer;
},
pause() {
const me = this;
clearInterval(me.timer);
me.$emit('pause', me.uid, true);
},
continues() {
const me = this;
me.initWriter(me.contentList);
},
reset() {
const me = this;
me.initPosition = 0;
me.initWriter(me.contentList);
}
}
};
</script>
<style scoped lang="scss">
.type-writer-container {
width: 100%;
height: auto;
}
</style>
使用方式
<template>
<view class="container">
<view class="type-writer-content" v-for="(item,index) in list" :key="index">
<type-writer :uid="item.uid" :ref="`writer${item.uid}`" :contentList="item.contentList" :delaytime="item.delaytime"></type-writer>
</view>
<button @click="pause(0)">暂停打字</button>
<button @click="continues(0)">继续打字</button>
<button @click="reset(0)">重置</button>
</view>
</template>
<script>
import typeWriter from '../../components/type-writer.vue';
export default {
components: { typeWriter },
data() {
return {
list: [
{
contentList: ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'],
delayTime: 300,
uid: 0
}
]
};
},
onLoad() {
setTimeout(() => {
this.list.push({
contentList: ['bbbbbbbbbbbbbbbbbbbbbbbbbbb', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'],
delayTime: 500,
uid: 1
});
}, 2000);
setTimeout(() => {
this.list[1].contentList = this.list[1].contentList.concat(['ccccccccccccccccccccccccccccccccccc']);
}, 5000);
},
methods: {
finish(id, status) {
console.log(1, id, status);
},
pause(id, status) {
this.$refs[`writer${id}`][0].pause();
},
continues(id, status) {
this.$refs[`writer${id}`][0].continues();
},
reset(id, status) {
this.$refs[`writer${id}`][0].reset();
}
}
};
</script>
<style lang="scss">
.container {
padding: 50upx;
.type-writer-content {
max-width: 60vw;
border: 1upx solid #ccc;
white-space: pre-wrap;
word-wrap: break-word;
padding: 15upx 30upx;
border-radius: 50upx;
margin: 20upx auto;
}
}
</style>