fix(canvas): 保护生成中与失败节点画幅尺寸,支持变体即时持久化与 2K 分辨率高亮 (#359)

Co-authored-by: Danborad <danborad@github.com>
This commit is contained in:
DanboradandDanborad authored and GitHub committed 2026-08-31 12:28:12 +08:00
1 parent 76e5a166dc
commit 8d9ab03a66
10 files changed
+127 -77

No files matched your search

+43 -12
View File
@@ -17,11 +17,34 @@ export function fitNodeSize(width: number, height: number, maxWidth = 720, maxHe
export function nodeSizeFromRatio(size: string, baseWidth: number, baseHeight: number) {
const raw = String(size || "").trim();
if (!raw || raw.toLowerCase() === "auto") return null;
// 支持 16:9 / 1024x576 / 16:9-2k
let width = 0;
let height = 0;
const match = raw.match(/^(\d+(?:\.\d+)?)(?:x|:)(\d+(?:\.\d+)?)/i);
if (!match) return null;
const width = Number(match[1]);
const height = Number(match[2]);
if (match) {
width = Number(match[1]);
height = Number(match[2]);
} else if (raw.includes("竖") || raw.includes("portrait") || raw.includes("9:16")) {
width = 9;
height = 16;
} else if (raw.includes("横") || raw.includes("landscape") || raw.includes("16:9")) {
width = 16;
height = 9;
} else if (raw.includes("(1:1)") || raw.includes("1:1") || raw.includes("square")) {
width = 1;
height = 1;
} else if (raw.includes("3:4")) {
width = 3;
height = 4;
} else if (raw.includes("4:3")) {
width = 4;
height = 3;
} else if (raw.includes("2:3")) {
width = 2;
height = 3;
} else if (raw.includes("3:2")) {
width = 3;
height = 2;
}
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return null;
const ratio = width / Math.max(1, height);
if (ratio < 0.25 || ratio > 4) return { width: baseWidth, height: baseHeight };
@@ -35,14 +58,22 @@ export function ensureMediaNodeMinimumSize(node: CanvasNodeData) {
let width = node.width;
let height = node.height;
const emptyStage = isBuiltinCanvasNodeType(node.type) ? NODE_DEFAULT_SIZE[node.type] : undefined;
const shouldPromoteEmptyStage = !node.metadata?.content
&& !node.metadata?.freeResize
&& !node.metadata?.locked
&& emptyStage !== undefined
&& width * height < emptyStage.width * emptyStage.height;
if (shouldPromoteEmptyStage) {
width = emptyStage.width;
height = emptyStage.height;
// 如果未完成节点(生成中/失败/空节点)指定了目标比例(如 3:4, 9:16),按目标比例保持占位框尺寸,不能强制变成 16:9 横屏。
const targetSize = node.metadata?.size ? nodeSizeFromRatio(node.metadata.size, emptyStage?.width || 720, emptyStage?.height || 405) : null;
if (targetSize && !node.metadata?.content && !node.metadata?.freeResize && !node.metadata?.locked) {
width = targetSize.width;
height = targetSize.height;
} else {
const shouldPromoteEmptyStage = !node.metadata?.content
&& !node.metadata?.freeResize
&& !node.metadata?.locked
&& emptyStage !== undefined
&& (width <= 0 || height <= 0);
if (shouldPromoteEmptyStage) {
width = emptyStage.width;
height = emptyStage.height;
}
}
const naturalWidth = node.metadata?.naturalWidth || 0;
const naturalHeight = node.metadata?.naturalHeight || 0;