无线画布项目问题汇总与解决方案
从 AI 短剧平台的 Canvas 编辑器、Agora 语音通话、上万条素材库虚拟滚动等 6 个真实问题,复盘踩坑与解决方案。
项目背景
星河万象是一个面向 AI 短剧行业的智能生成平台,包含无限画布节点编辑器、3D 导演台、资源库、权限系统等核心模块。我在其中负责前端架构、Canvas 图片编辑器、实时语音通话、海量素材库等关键能力。下面的 6 个问题全部来自真实开发文档,是我在项目中一步步踩坑并解决出来的经验。
Canvas 弹窗第一次打开不显示图像
🎯现象
图片编辑器第一次打开弹窗时画布空白,第二次打开才正常显示。
🔍根因
canvasWidth / canvasHeight 初始为 760×530,打开弹窗时 initCanvas() 根据原图尺寸动态更新这两个响应式值并立即绘制;但 Vue 绑定到 canvas 的 width/height 属性会在下一次 DOM 更新时再次修改 canvas,而浏览器修改 canvas 尺寸会自动清空画布,导致第一次绘制被清空。第二次打开时尺寸已经稳定,不再触发清空。
✅解决
把 canvas 尺寸初始化与绘制拆分到 DOM 更新后执行;或者用离屏 canvas 先完成绘制再一次性渲染,避免尺寸绑定与绘制顺序冲突。
矩形绘制位置与鼠标位置偏移
🎯现象
在 Canvas 上画矩形时,起点位置与鼠标落点不一致。
🔍根因
用 CSS 的 width/height 控制 canvas 显示尺寸,导致像素坐标与显示坐标不统一;同时 transform 缩放/平移后没有同步修正鼠标坐标。
✅解决
让 canvas 的像素尺寸与显示尺寸保持一致,取消 CSS 强制缩放;同时把鼠标事件坐标通过 getBoundingClientRect 换算到 canvas 像素坐标,确保绘制位置与游标位置一致。
图片编辑后保存变模糊
🎯现象
高清原图经过画布编辑后导出,像素明显变模糊。
🔍根因
保存时直接用屏幕显示分辨率导出,没有区分“显示分辨率”和“原始像素”;文本层/拖拽层也没有同步画布的缩放与偏移。
✅解决
保存采用“原图尺寸离屏绘制”,文本显示和拖拽使用 displayScale + zoom 联合缩放;文本编辑时让画布与文本层应用同样的 transform,并同步事件到父组件。
Agora 语音通话的异常场景处理
🎯场景
在现有聊天 UI 中接入 Agora 音频通话,需要处理来电弹窗、忙线、超时、UID 冲突等状态。
🔍方案
复用现有 WebSocket 聊天通道作为信令,约定 ___VOICE_CALL___ / ___VOICE_ACCEPT___ / ___VOICE_REJECT___ / ___VOICE_HANGUP___ / ___VOICE_BUSY___ 固定标记转发;chatService 支持多 handler 注册,避免互相覆盖。
被叫端 30s 无操作自动关闭弹窗,发起端显示“对方无响应”;非 idle 状态自动回复 VOICE_BUSY。UID 冲突时捕获 UID_CONFLICT 错误后重试 join(uid = null 让 Agora 自动分配)。
海量素材库滚动卡顿
🎯现象
素材库包含上千甚至上万条图片/视频记录,滚动时 DOM 节点爆炸、视频预加载、内存泄漏,页面明显卡顿。
🔍方案
采用虚拟滚动只渲染可视区域内少量 DOM,通过 translateY 做 GPU 加速位移,DOM 节点复用;首屏用 Canvas 截取视频首帧生成封面,按需创建 video 并立即销毁,避免后台缓冲;滚动用 IntersectionObserver 替代 scroll 事件,500ms 防抖;缓存上限 150 条,自动清理过期数据。
另外可用阿里云 OSS 视频快照参数 ?x-oss-process=video/snapshot,t_0,f_jpg,w_100,m_fast,ar_auto 获取首帧缩略图,进一步减少前端计算。
Element Plus 表格自定义行背景不生效
🎯现象
给 el-table 的选中行设置渐变背景,实际没有生效。
🔍根因
Element Plus 会给每个 td 设置默认背景色,子元素 td 的背景完全覆盖了父级 tr 设置的渐变背景。
✅解决
用 :deep(.el-table td) 把 td 背景设为透明,让父级 tr.selected-row 的渐变背景透出来;同时通过 row-class-name 控制选中行,并覆盖 hover 背景保持样式一致。
总结
星河万象这类 AI 内容生产平台,核心挑战在于:复杂 Canvas 编辑器的坐标与渲染一致性、大规模媒体资源的性能与内存管理、实时音视频通话的异常状态兜底。通过分层渲染、坐标统一、虚拟滚动、信令复用、OSS 能力结合等方案,最终让平台在可维护性和用户体验之间达到了较好的平衡。