Live2D AI聊天功能折腾日记:从“僵尸框”到完美交互
最近在给个人网站加一个基于 LLM 的 AI 看板娘功能。技术栈选了 Next.js + React,看板娘库用了 oh-my-live2d。
本以为调个 API 就完事了,结果在状态管理、组件生命周期和库的默认行为上踩了一下午的坑。特此记录一下这段“折腾”经历,希望能帮到后来人。
随着折腾的深入,会逐渐补充。
# 背景需求
我的需求中间发生了多次变更和补充,最终我想实现的功能是这样的:
网页右下角有个看板娘。
点击看板娘菜单的“睡觉”,她会消失;为了防止别人压根看不到聊天功能,页面上有一个“星星”按钮,点击页面上的“星星”按钮,她会出来并打开 AI 对话框。
状态要持久化:用户关掉了,刷新页面不能又跳出来。
智能欢迎语:看板娘出来时,要根据时间段打招呼(早上好/晚上好),但如果是点击“星星”唤起的,要说“AI已就绪”。
# 默认欢迎语的“僵尸框”
# 问题
库自带了一个 welcomeTips 功能。我想禁掉它,改用我自己的逻辑:
如果是第一次点进网页,欢迎语需要告诉用户可以点击左侧按钮与我聊天;但如果是点击星星按钮打开的,就不需要再提示用户“欢迎与我聊天”而是直接说“早上好”这种话就够了。
我一开始尝试把文案设为空,但是出现一个空白蓝色框。
再尝试把duration设为 0,结果还是会闪一下。
尝试 CSS opacity: 0 ,然后过几秒再调整,这样我自己的聊天框也展示不了而且方法过于丑陋。
# 💡 瞎搞出的奇迹方案
在绝望中尝试把优先级 priority 设为负数,结果......完美解决!库内部应该是过滤掉了负优先级的消息。
// 配置里这样写
welcomeTips: {
priority: -1, // <--- 神之一手,直接让默认欢迎语闭嘴
},
2
3
4
5
6
# React Hooks 的使用规则
# 问题
我想在 Store 的 setInstance 方法里计算欢迎语,结果报了 Invalid hook call。 原因:useTranslation 是 React Hook,不能在 Zustand 的纯函数里调用。
# 解决:职责分离
组件层:负责用 Hooks (useTranslation) 算好要说什么话。
Store 层:只负责接收字符串并执行 instance.tipsMessage()。
当然,后来我发现了onSlideIn钩子,可以统一直接设置钩子函数,在看板娘入场动画结束后说话,无需在别的地方加一堆判断,这样用户体验更好一些。
# 总结
这一通折腾下来,不仅搞定了功能,对前端的生命周期、状态同步有了更深的理解。
不要在 Hook 外面调 Hook。
涉及动画的 UI 库,永远不要相信 setTimeout,要找回调事件。
有时候“瞎搞”(比如 priority: -1)真的能解决大问题。