@mingto/type-writer
v1.0.6
Published
流式打字机效果组件,提供逐字符显示文本的打字机效果
Maintainers
Readme
@mingto/type-writer
TypeScript 打字机效果工具库,支持逐字输出文本,模拟打字机般的视觉效果。轻量级、高性能、零依赖。
特性
- ⌨️ 打字机效果:逐字输出文本,模拟真实打字机体验
- ⚡ 自定义速度:灵活配置打字速度,毫秒级精确控制
- 🎯 事件驱动:支持
change和complete两种事件回调 - 📦 TypeScript 支持:完整的类型定义和类型推导,IDE 智能提示
- 🔄 队列机制:支持连续发送文本,自动排队处理,无需手动管理
- 🚫 状态管理:完整的生命周期管理(PENDING/EXECUTING/COMPLETED)
- 💎 链式调用:流畅的 API 链式调用设计,代码更优雅
- 🚀 零依赖:无任何外部依赖,体积小巧,易于集成
- 🎨 框架无关:不绑定任何框架,支持 Vue、React、Angular 等所有主流框架
安装
# npm
npm install @mingto/type-writer
# yarn
yarn add @mingto/type-writer
# pnpm (推荐)
pnpm add @mingto/type-writer快速开始
三行代码实现打字机效果:
import { createTypeWriter } from '@mingto/type-writer'
// 1. 创建打字机实例
const typeWriter = createTypeWriter({ speed: 100 })
// 2. 监听事件
typeWriter.on('change', (text) => {
document.getElementById('typing-text').innerText = text
})
// 3. 发送文本开始打字
typeWriter.send('Hello, World! 你好,世界!')API 文档
创建实例
createTypeWriter(options)
创建打字机实例。
import { createTypeWriter } from '@mingto/type-writer'
const typeWriter = createTypeWriter({
speed: 100, // 每字间隔 100ms
})配置参数 options:
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| speed | number | ❌ | 100 | 打字速度,单位为毫秒/每字 |
实例方法
typeWriter.send(text)
发送文本进行打字机输出,支持链式调用。
typeWriter.send('这是第一段文本。')
// 可连续调用,文本会排队处理
typeWriter.send('这是第二段文本。')| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| text | string | ✅ | 要输出的文本 |
typeWriter.end()
手动结束打字机,完成剩余字符输出。
typeWriter.end()typeWriter.finish()
销毁打字机实例,清除定时器和队列,释放资源。
typeWriter.finish()typeWriter.getText()
获取当前已输出的完整文本。
const currentText = typeWriter.getText()
console.log(currentText)typeWriter.on(eventName, callback)
监听事件,支持链式调用。
typeWriter
.on('change', (text) => {
console.log('输出变更:', text)
})
.on('complete', () => {
console.log('全部完成')
})事件说明
| 事件名 | 触发时机 | 回调参数 | 说明 |
|--------|----------|----------|------|
| change | 每次有新字符输出时 | string | 返回当前已输出的完整文本 |
| complete | 所有字符输出完成时 | - | 标志打字过程结束 |
使用示例
基础用法
import { createTypeWriter } from '@mingto/type-writer'
const tw = createTypeWriter({ speed: 150 })
tw
.on('change', (text) => {
document.getElementById('output').textContent = text
})
.on('complete', () => {
console.log('打字完成!')
})
tw.send('欢迎使用 type-writer 打字机效果库!')快速打字效果
import { createTypeWriter } from '@mingto/type-writer'
const fastTw = createTypeWriter({ speed: 50 })
fastTw
.on('change', (text) => {
console.log(text)
})
.on('complete', () => {
console.log('快速打字完成')
})
fastTw.send('这是快速打字效果的演示文本。')慢速打字效果
import { createTypeWriter } from '@mingto/type-writer'
const slowTw = createTypeWriter({ speed: 300 })
slowTw
.on('change', (text) => {
console.log(text)
})
slowTw.send('这是慢速打字效果,每个字间隔 300ms,适合营造悬念氛围。')在 React 中使用
import { useState, useEffect, useRef } from 'react'
import { createTypeWriter } from '@mingto/type-writer'
const TypeWriterComponent = () => {
const [text, setText] = useState('')
const [isComplete, setIsComplete] = useState(false)
const typeWriterRef = useRef(null)
useEffect(() => {
typeWriterRef.current = createTypeWriter({
speed: 100,
})
typeWriterRef.current
.on('change', (currentText) => {
setText(currentText)
})
.on('complete', () => {
setIsComplete(true)
})
.send('欢迎来到我们的网站!这是一段打字机效果演示文本。')
return () => {
typeWriterRef.current?.finish()
}
}, [])
return (
<div>
<span>{text}</span>
{!isComplete && <span className="cursor">|</span>}
</div>
)
}
export default TypeWriterComponent在 Vue 3 中使用
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import { createTypeWriter } from '@mingto/type-writer'
const displayText = ref('')
const isComplete = ref(false)
let typeWriter = null
onMounted(() => {
typeWriter = createTypeWriter({ speed: 80 })
typeWriter
.on('change', (text) => {
displayText.value = text
})
.on('complete', () => {
isComplete.value = true
})
.send('Vue 3 打字机效果演示。优雅的逐字输出体验。')
})
onUnmounted(() => {
typeWriter?.finish()
})
</script>
<template>
<div class="type-writer">
<span>{{ displayText }}</span>
<span v-if="!isComplete" class="cursor">_</span>
</div>
</template>连续发送多段文本
import { createTypeWriter } from '@mingto/type-writer'
const tw = createTypeWriter({ speed: 100 })
tw
.on('change', (text) => {
process.stdout.write(`\r${text}`)
})
.on('complete', () => {
console.log('\n全部完成!')
})
// 第一段
tw.send('第一段文本。')
// 1 秒后发送第二段
setTimeout(() => {
tw.send('第二段文本,排队输出。')
}, 1000)
// 2 秒后发送第三段
setTimeout(() => {
tw.send('第三段文本,继续输出。')
}, 2000)结合语音识别显示实时结果
import { createTypeWriter } from '@mingto/type-writer'
import huoshanLAT from '@mingto/huoshan-lat'
// 创建打字机实例
const tw = createTypeWriter({ speed: 30 })
tw.on('change', (text) => {
document.getElementById('asr-result').innerText = text
})
// 配置语音识别
huoshanLAT.config()
const lat = huoshanLAT.create({}, {
autoControl: true,
initialDelay: 3500,
subsequentDelay: 3000,
})
lat.on('appResultText', (text) => {
// 用打字机效果显示语音识别结果
tw.send(text + ' ')
})
lat.watch()最佳实践
1. 速度配置建议
| 使用场景 | 推荐速度 | 说明 | |----------|----------|------| | 标题展示 | 80-150ms | 吸引用户注意力 | | 正文内容 | 50-100ms | 平衡阅读体验和效率 | | 强调文本 | 150-300ms | 突出重点,营造悬念 | | 快速提示 | 20-50ms | 追求效率,不影响阅读 |
2. 文本分段建议
- 长文本:建议按句子或段落分段发送,每段 50-100 字
- 对话内容:按角色发言分段,增强对话感
- 列表内容:按条目逐个发送,增强层次感
// ❌ 不推荐:一次性发送超长文本
tw.send('非常长的一段文本,可能导致用户阅读压力...')
// ✅ 推荐:分段发送
tw.send('第一段内容。')
setTimeout(() => tw.send('第二段内容。'), 3000)3. 性能优化
// ✅ 推荐:在组件卸载时清理资源
useEffect(() => {
const tw = createTypeWriter({ speed: 100 })
return () => tw.finish()
}, [])
// ❌ 避免:创建多个实例而不清理
const tw1 = createTypeWriter({ speed: 100 })
const tw2 = createTypeWriter({ speed: 100 }) // 不必要状态说明
| 状态 | 值 | 说明 |
|------|----|------|
| PENDING | 'pending' | 待执行状态,等待输入文本 |
| EXECUTING | 'executing' | 执行中状态,正在进行打字输出 |
| COMPLETED | 'completed' | 已完成状态,所有文本输出完毕 |
状态流转:
PENDING → EXECUTING → COMPLETED内部工作流程
- 初始化阶段:创建实例,设置默认参数
- 接收文本:调用
send()方法,将文本加入队列 - 逐字输出:按设定速度逐字输出文本,触发
change事件 - 完成回调:所有字符输出完成后,触发
complete事件 - 资源释放:调用
finish()清除定时器和队列
注意事项
- ⚠️ 组件卸载清理:在页面卸载或组件销毁时,务必调用
finish()方法释放资源,避免内存泄漏 - ⚠️ 速度设置:建议速度值在 30-300ms 之间,太快可能看不清,太慢影响体验
- ⚠️ 文本长度:过长文本建议分段发送,可获得更好的用户体验
- ⚠️ 事件回调:
change事件会频繁触发,避免在回调中执行耗时操作 - ⚠️ 链式调用:
on和send方法支持链式调用,让代码更简洁优雅 - ⚠️ 手动结束:调用
end()会立即完成所有剩余字符的输出
常见问题
Q: 如何实现光标闪烁效果? A: 可以使用 CSS 动画实现:
.cursor {
animation: blink 1s infinite;
}
@keyframes blink {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}Q: 如何实现打字暂停和恢复? A: 可以通过自定义逻辑实现:
let paused = false
const originalText = '要输出的文本'
let currentIndex = 0
const tw = createTypeWriter({ speed: 100 })
function pause() {
paused = true
// 保存当前状态
}
function resume() {
paused = false
// 继续输出剩余文本
tw.send(originalText.slice(currentIndex))
}Q: 打字速度可以动态调整吗? A: 目前不支持动态调整,需要重新创建实例。建议根据场景预设不同的速度配置。
Q: 支持输出 HTML 内容吗? A: 目前只支持纯文本输出。如果需要 HTML,可以在回调中手动处理富文本渲染。
浏览器兼容性
| Chrome | Firefox | Safari | Edge | IE | |--------|---------|--------|------|----| | 60+ | 55+ | 12+ | 79+ | ❌ 不支持 |
需要支持
requestAnimationFrame和setTimeoutAPI
性能指标
| 指标 | 数值 | 说明 | |------|------|------| | 打包后大小 | ~2KB | gzip 压缩后 | | 内存占用 | <1MB | 正常使用场景 | | CPU 使用率 | <1% | 打字过程中 | | 初始化耗时 | <1ms | 几乎瞬时 |
相关链接
许可证
MIT
