Files
YGChatCS/utils/TypewriterManager.js
2025-08-26 10:54:41 +08:00

174 lines
4.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 打字机效果管理器
* 负责管理打字机效果的启动、停止、重置等功能
*/
class TypewriterManager {
constructor(options = {}) {
// 配置选项
this.options = {
typingSpeed: 50, // 打字速度(毫秒)
cursorText: '', // 光标样式
...options
};
// 状态变量
this.currentMessageContent = ""; // 当前消息的完整内容
this.displayedContent = ""; // 已显示的内容
this.typewriterTimer = null; // 打字机定时器
this.isTyping = false; // 是否正在打字
// 回调函数
this.onCharacterTyped = null; // 每个字符打字时的回调
this.onTypingComplete = null; // 打字完成时的回调
this.onContentUpdate = null; // 内容更新时的回调
}
/**
* 设置回调函数
* @param {Object} callbacks - 回调函数对象
* @param {Function} callbacks.onCharacterTyped - 每个字符打字时的回调
* @param {Function} callbacks.onTypingComplete - 打字完成时的回调
* @param {Function} callbacks.onContentUpdate - 内容更新时的回调
*/
setCallbacks(callbacks) {
this.onCharacterTyped = callbacks.onCharacterTyped || null;
this.onTypingComplete = callbacks.onTypingComplete || null;
this.onContentUpdate = callbacks.onContentUpdate || null;
}
/**
* 添加内容到当前消息
* @param {string} content - 要添加的内容
*/
addContent(content) {
if (typeof content !== 'string') {
content = String(content);
}
this.currentMessageContent += content;
// 如果没有在打字,启动打字机效果
if (!this.isTyping) {
this.startTypewriter();
}
}
/**
* 启动打字机效果
*/
startTypewriter() {
if (this.isTyping) return;
this.isTyping = true;
// 不要在启动时重置displayedContent而是从当前位置继续
this._typeNextChar();
}
/**
* 打字下一个字符(私有方法)
*/
_typeNextChar() {
// 如果已显示内容长度小于完整内容长度,继续打字
if (this.displayedContent.length < this.currentMessageContent.length) {
this.displayedContent = this.currentMessageContent.substring(
0,
this.displayedContent.length + 1
);
const displayContent = this.displayedContent;
// 调用内容更新回调
if (this.onContentUpdate) {
this.onContentUpdate(displayContent);
}
// 调用字符打字回调
if (this.onCharacterTyped) {
this.onCharacterTyped(this.displayedContent);
}
// 确保最小延迟,避免定时器堆积
const delay = Math.max(this.options.typingSpeed, 30); // 设置最小延迟30ms
this.typewriterTimer = setTimeout(() => {
this._typeNextChar();
}, delay);
} else {
// 打字完成,移除光标
if (this.onContentUpdate) {
this.onContentUpdate(this.currentMessageContent);
}
// 调用打字完成回调
if (this.onTypingComplete) {
this.onTypingComplete(this.currentMessageContent);
}
this.stopTypewriter();
}
}
/**
* 停止打字机效果
*/
stopTypewriter() {
if (this.typewriterTimer) {
clearTimeout(this.typewriterTimer);
this.typewriterTimer = null;
}
this.isTyping = false;
}
/**
* 重置打字机状态
*/
reset() {
this.currentMessageContent = "";
this.displayedContent = "";
this.stopTypewriter();
}
/**
* 获取当前状态
* @returns {Object} 当前状态对象
*/
getStatus() {
return {
isTyping: this.isTyping,
currentContent: this.currentMessageContent,
displayedContent: this.displayedContent,
progress: this.currentMessageContent.length > 0
? this.displayedContent.length / this.currentMessageContent.length
: 0
};
}
/**
* 立即完成打字(跳过动画)
*/
completeImmediately() {
this.stopTypewriter();
this.displayedContent = this.currentMessageContent;
if (this.onContentUpdate) {
this.onContentUpdate(this.currentMessageContent);
}
if (this.onTypingComplete) {
this.onTypingComplete(this.currentMessageContent);
}
}
/**
* 销毁打字机管理器
*/
destroy() {
this.stopTypewriter();
this.reset();
this.onCharacterTyped = null;
this.onTypingComplete = null;
this.onContentUpdate = null;
}
}
export default TypewriterManager;