/** * 打字机效果管理器 * 负责管理打字机效果的启动、停止、重置等功能 */ 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) { const nextLength = Math.min( this.displayedContent.length + 1, this.currentMessageContent.length ); this.displayedContent = this.currentMessageContent.substring( 0, nextLength ); 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; } /** * 停止打字机效果并保留当前显示的内容 * 与stopTypewriter不同,这个方法会将当前显示的内容设为最终内容 */ stopAndKeepCurrent() { this.stopTypewriter(); // 将当前显示的内容设为完整内容,避免后续添加更多内容 this.currentMessageContent = this.displayedContent; // 调用完成回调 if (this.onTypingComplete) { this.onTypingComplete(this.displayedContent); } } /** * 重置打字机状态 */ 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;