feat(canvas): 优化图片和视频节点尺寸适配

- 在 InsertAssetPayload 类型中为视频添加 width 和 height 属性
- 引入 fitNodeSize 和 nodeSizeFromRatio 工具函数处理节点尺寸计算
- 设置视频节点最大宽度和高度限制为 420px
- 将原有的 fitImageNodeSize 替换为通用的 fitNodeSize 函数
- 为视频节点添加自然宽高元数据存储
- 实现视频文件上传时读取真实宽高信息
- 支持空节点在尺寸比例切换时自动调整外框大小
- 修复视频节点在生成和重试过程中的尺寸适配问题
- 统一图片和视频节点的尺寸调整逻辑
- 添加视频节点纵横比锁定功能
This commit is contained in:
HouYunFei
2026-05-23 18:30:32 +08:00
parent ef7772a703
commit f871a5d015
6 changed files with 66 additions and 34 deletions
@@ -12,7 +12,7 @@ import { fetchAssetLibrary, type AssetLibraryItem } from "@/services/api/assets"
export type AssetPickerTab = "my-assets" | "library";
export type InsertAssetPayload = { kind: "text"; content: string; title: string } | { kind: "image"; dataUrl: string; title: string; storageKey?: string } | { kind: "video"; url: string; title: string; storageKey?: string };
export type InsertAssetPayload = { kind: "text"; content: string; title: string } | { kind: "image"; dataUrl: string; title: string; storageKey?: string } | { kind: "video"; url: string; title: string; storageKey?: string; width?: number; height?: number };
type Props = {
open: boolean;
@@ -207,7 +207,7 @@ function MyAssetsTab({ onInsert }: { onInsert: (payload: InsertAssetPayload) =>
if (asset.kind === "text") {
onInsert({ kind: "text", content: asset.data.content, title: asset.title });
} else {
onInsert(asset.kind === "video" ? { kind: "video", url: asset.data.url, storageKey: asset.data.storageKey, title: asset.title } : { kind: "image", dataUrl: asset.data.dataUrl, storageKey: asset.data.storageKey, title: asset.title });
onInsert(asset.kind === "video" ? { kind: "video", url: asset.data.url, storageKey: asset.data.storageKey, title: asset.title, width: asset.data.width, height: asset.data.height } : { kind: "image", dataUrl: asset.data.dataUrl, storageKey: asset.data.storageKey, title: asset.title });
}
};
@@ -209,7 +209,7 @@ export const CanvasNode = React.memo(function CanvasNode({
startTop: data.position.y,
startWidth: data.width,
startHeight: data.height,
keepRatio: data.type === CanvasNodeType.Image && !data.metadata?.freeResize,
keepRatio: (data.type === CanvasNodeType.Image && !data.metadata?.freeResize) || data.type === CanvasNodeType.Video,
ratio: (data.metadata?.naturalWidth || data.width) / (data.metadata?.naturalHeight || data.height || 1),
};
window.addEventListener("mousemove", handleResizeMove);