Appearance
html
<script lang="ts" setup>
import { defineProps, ref, watch, withDefaults } from 'vue'
const { array, typeSpeed, delay, start, caret, iterations } = withDefaults(
defineProps<{
array: string[]
typeSpeed: number
delay: number
start: number
caret: string
iterations: number
}>(),
{
typeSpeed: 200,
delay: 2000,
start: 0,
caret: 'cursor',
iterations: 0
}
)
const emit = defineEmits(['typed', 'typeStatus'])
const typeValue = ref('')
const count = ref(0)
const typeStatus = ref(false)
const arrayIndex = ref(0)
const charIndex = ref(0)
function typewriter() {
let loop = 0
if (charIndex.value < array[arrayIndex.value].length) {
if (!typeStatus.value) {
typeStatus.value = true
}
typeValue.value += array[arrayIndex.value].charAt(charIndex.value)
charIndex.value += 1
setTimeout(typewriter, typeSpeed)
} else {
count.value += 1
onTyped(array[arrayIndex.value])
if (count.value === array.length) {
loop += 1
if (loop === iterations) {
return (typeStatus.value = false)
}
}
typeStatus.value = false
setTimeout(eraser, delay)
}
}
function eraser() {
// if (charIndex.value > 0) {
// if (!typeStatus.value) typeStatus.value = true
// typeValue.value = array[arrayIndex.value].substring(0, charIndex.value - 1)
// charIndex.value -= 1
// setTimeout(eraser, eraseSpeed)
// } else {
// typeStatus.value = false
charIndex.value = 0
typeValue.value = ''
arrayIndex.value += 1
if (arrayIndex.value >= array.length) arrayIndex.value = 0
setTimeout(typewriter, 0)
// }
}
function onTyped(typedString: string) {
emit('typed', typedString)
}
setTimeout(typewriter, start)
watch(
() => typeStatus.value,
(val) => {
emit('typeStatus', val)
}
)
</script>
<template>
<div class="is-typed">
<slot></slot>
<span class="typed">{{ typeValue }}</span>
<span :class="caret + ' ' + { typing: typeStatus }"> </span>
</div>
</template>
<style lang="less" scoped>
.cursor {
display: inline-block;
width: 2px;
margin: 0 2px;
background: #333;
border-radius: 2px;
transform: scaleY(0.9);
}
</style>调用
js
const subTitle = ref<string[]>([
'第一句话',
'第二话',
'第三句话',
'结束了'
])
<Writer :array="subTitle" :type-speed="70" :delay="5000" />