Files
TrueGrowth/docs/PPT_FRAME_ASSET_INSERTION_LESSONS.md

3.9 KiB
Raw Blame History

PPT Frame 素材插入经验

更新日期2026-04-27

背景

用户在画布中选中 PPT 页面(底层为 Frame)后,从素材库或生成结果插入图片/视频,预期素材进入当前 PPT 页面并自适应页面尺寸。旧逻辑只把素材插入到选中元素下方导致素材落在页面外需要用户手动拖入和执行「素材自适应PPT」。

经验

1. 先复用 Frame 内部插入能力

insertMediaIntoFrame 已经覆盖 Frame 查找、contain/stretch 适配、居中放置和 frameId 绑定。新需求不要再在素材库、任务队列、AI 预览等入口各写一套几何逻辑,只在通用插入链路前置识别「单选 Frame」即可。

2. 单选 Frame 才改变插入语义

只有当前 selection 或 appState.lastSelectedElementIds 是单个 Frame 时,才插入到 Frame 内。多选、选中普通元素、拖拽指定坐标、显式传入 startPoint/referenceDimensions 时,应继续沿用原插入位置,避免破坏批量排列和拖拽语义。

3. PPT 自适应要用 contain不要默认拉伸

插入到 PPT 页面内的图片/视频应保持媒体比例并居中适配 Frame。只有明确传 { fit: 'stretch' } 时才铺满页面,避免素材变形。视频没有真实尺寸时可用 16:9 兜底,但如果上层已传媒体尺寸,必须尊重该尺寸计算适配。

4. 插入后必须绑定 frameId

PPT 导出、Frame 移动、预览缩略图和「素材自适应PPT」都依赖 frameId 或几何相交关系。插入时直接绑定 frameId,比后续靠最大相交面积补救更稳定。

5. 底层修复优先于入口补丁

素材插入入口很多素材库、任务队列、AI 预览、MCP/工作流、快捷工具栏。修在 insertImageFromUrlinsertVideoFromUrlexecuteCanvasInsertion 这类公共层,能覆盖更多路径,也减少后续漏改风险。

实现要点

  • 新增 getSelectedInsertionFrame:优先读当前 selectionselection 为空时回退 lastSelectedElementIds
  • 新增 insertMediaIntoSelectedFrame:把选中 Frame 的 points 转为目标尺寸,再调用 insertMediaIntoFrame
  • 图片/视频通用插入函数在没有显式坐标和尺寸时,先尝试插入选中 Frame。
  • executeCanvasInsertion 对单个图片/视频内容做同样前置处理,覆盖 quickInsert、任务队列和 AI 预览。
  • 视频插入新增 lockReferenceDimensions,避免 Frame 适配后的尺寸再次被默认 16:9 逻辑改写。

注意事项

  • 不要为了「当前 PPT」新增实体或全局状态当前画布 selection 已经足够表达目标 Frame。
  • 不要在插入前完整下载视频元数据;高并发文件处理场景下应保持轻量,必要时使用传入尺寸或默认比例。
  • 不要让 startPoint 场景自动吸附 Frame拖拽和批量排版需要尊重调用方坐标。
  • 不要只改素材库按钮;生成结果、工作流和预览器也会走插入链路。

验证建议

  1. 指定文件测试:
pnpm --dir packages/drawnix exec vitest run src/utils/__tests__/frame-insertion-utils.test.ts src/utils/__tests__/ppt-media-fit.test.ts
  1. 类型检查:
pnpm nx run drawnix:typecheck
  1. 注意测试命令:
pnpm --filter @aitu/drawnix test -- frame-insertion-utils.test.ts

该写法会被当前包脚本吞成更大范围测试,可能暴露仓库既有 unrelated 失败。需要精确验证单文件时,优先使用 pnpm --dir packages/drawnix exec vitest run ...

检查清单

  • 单选 PPT 页面后插入图片,图片出现在页面内部并保持比例。
  • 单选 PPT 页面后插入视频,视频出现在页面内部并保持比例。
  • 插入后的媒体元素带有目标页面 frameId
  • 未选中 Frame 时,素材仍插入到原来的默认位置。
  • 传入显式 startPoint 的批量插入不被 Frame 逻辑劫持。