typewriter.ts
import type { Ref } from 'vue'
// 打字机效果函数的返回类型
type typewriterReturnType = {
writeTimer: NodeJS.Timeout
delTimer: NodeJS.Timeout | undefined
speedChangeTimer: NodeJS.Timeout
}
/**
* 打字机效果
*
* @param textRef 文本的 ref 响应式对象
* @param delEnable 是否开启文本的删除效果,默认开启
* @param speedChangeDuration 打字速度与删除文本速度改变的周期时间,默认 1500 ms
* @param writeSpeedMin 最小打字速度,每个字符出现的时间间隔,时间间隔越大该值越大,默认 350 ms
* @param writeSpeedMax 最大打字速度,每个字符出现的时间间隔,时间间隔越大该值越小,默认 75 ms
* @param delSpeedMin 最小删除速度,每个字符消失的时间间隔,时间间隔越大该值越大,默认 150 ms
* @param delSpeedMax 最大删除速度,每个字符消失的时间间隔,时间间隔越大该值越小,默认 50 ms
* @returns {typewriterReturnType} 返回改变打字速度与删除文本速度的定时器、打字定时器与删除文本定时器,
* 方便调用者对定时器进行清除
*/
const typewriter = (
textRef: Ref<string>,
delEnable: boolean = true,
speedChangeDuration: number = 1500,
writeSpeedMin: number = 350,
writeSpeedMax: number = 75,
delSpeedMin: number = 150,
delSpeedMax: number = 50,
): typewriterReturnType => {
// 打字定时器
let writeTimer: NodeJS.Timeout
// 删除文本定时器
let delTimer: NodeJS.Timeout | undefined
// 打字速度
let writeSpeed: number = genRandomIntBoth(writeSpeedMax, writeSpeedMin)
// 文本删除速度
let delSpeed: number
// 文本字符串
const text: string = textRef.value
// 当前要打字或删除的文本字符索引
let textIdx: number = 0
// 当前处于打字和删除文本哪个状态,true — 打字,false — 删除文本
let status: boolean = true
// 初始状态下,页面中无文本
textRef.value = ''
// 如果开启文本的删除效果
if (delEnable) {
delSpeed = genRandomIntBoth(delSpeedMax, delSpeedMin)
}
/**
* 打字效果
*/
function writing(): void {
// 写入文本字符
textRef.value += text[textIdx++]
// 文本写入完成
if (textIdx >= text.length) {
// 清除打字定时器
clearInterval(writeTimer)
// 如果开启了文本的删除效果
if (delEnable) {
// 修改状态
status = false
// 创建删除文本定时器
delTimer = setInterval(deleting, delSpeed)
} else {
// 清除文本,重新创建打字定时器
textRef.value = ''
textIdx = 0
writeTimer = setInterval(writing, writeSpeed)
}
}
}
/**
* 删除文本效果
*/
function deleting(): void {
// 删除文本字符
textRef.value = text.substring(0, textIdx--)
// 文本删除完成
if (textIdx < 0) {
// 清除删除文本定时器
clearInterval(delTimer)
// 重置当前要打字或删除的文本字符索引
textIdx = 0
// 修改状态
status = true
// 创建打字定时器
writeTimer = setInterval(writing, writeSpeed)
}
}
// 创建打字定时器,开启打字机效果
writeTimer = setInterval(writing, writeSpeed)
// 创建改变打字速度与删除文本速度的定时器
// 改变打字速度与删除文本速度的定时器
const speedChangeTimer: NodeJS.Timeout = setInterval(() => {
// 当前处于打字状态就只修改打字速度
if (status) {
// 改变打字速度
writeSpeed = genRandomIntBoth(writeSpeedMax, writeSpeedMin)
// 重新创建定时器
clearInterval(writeTimer)
writeTimer = setInterval(writing, writeSpeed)
return
}
// 当前处于删除文本状态就只修改删除文本速度
// 如果开启了文本的删除效果
if (delEnable) {
// 改变删除文本速度
delSpeed = genRandomIntBoth(delSpeedMax, delSpeedMin)
// 重新创建定时器
clearInterval(delTimer)
delTimer = setInterval(deleting, delSpeed)
}
}, speedChangeDuration)
// 返回改变打字速度与删除文本速度的定时器、打字定时器与删除文本定时器,
// 方便调用者对定时器进行清除
return {
writeTimer,
delTimer,
speedChangeTimer,
}
}
export default typewriter
css
/******************************* 打字机效果中的光标 *******************************/
/* 打字机效果中的光标 */
/* 在文本内容的最后通过添加行内元素以达到光标跟随文字的输入移动的效果 */
.typewriter::after {
content: '|';
animation: cursor-blinks 1s infinite;
}
/* 光标闪烁动画 */
@keyframes cursor-blinks {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}