From 16e20ff63c610c4adf8a1bf338498cc7a2b4b034 Mon Sep 17 00:00:00 2001 From: saas-backend-agent Date: Wed, 23 Sep 2026 14:10:42 +0800 Subject: [PATCH] =?UTF-8?q?fix(title):=20=E9=A2=84=E8=A7=88=E5=8C=BA?= =?UTF-8?q?=E6=A0=87=E9=A2=98=E6=A0=B7=E5=BC=8F=E5=BA=94=E7=94=A8=E7=9C=9F?= =?UTF-8?q?=E5=AE=9E=E6=A8=A1=E6=9D=BF=E6=8F=8F=E8=BE=B9/=E9=98=B4?= =?UTF-8?q?=E5=BD=B1/=E8=83=8C=E6=99=AF=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:FrontendPreviewPlayer 渲染视频预览标题时,描边宽度/颜色、阴影偏移/模糊/颜色、背景色块都被硬编码(如黑描边2px、固定2px阴影、无背景),选模板后预览文字不显示模板真实样式(例如抖音爆款黄的8px黑描边只显示2px)。 修复: - FrontendPreviewPlayer 扩展 titleSettings props,接收 strokeWidth/strokeColor/shadowOffsetX/Y/shadowBlur/shadowColor/bgEnabled/bgColor/bgPadding/bgRadius/lineHeight 字段 - 所有描边/阴影/背景值按容器等比缩放后用于 CSS - CanvasPreviewGrid 传递 titleSettings 时补充上述字段,批量预览同步生效 - 删除不再使用的 titleScale 常量 - 数字人侧 PanelLipsyncPreview 已正确读字段,无需改动 --- .../generate/components/CanvasPreviewGrid.tsx | 12 +++++ .../components/FrontendPreviewPlayer.tsx | 47 +++++++++++++++---- 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/apps/web/src/pages/generate/components/CanvasPreviewGrid.tsx b/apps/web/src/pages/generate/components/CanvasPreviewGrid.tsx index 20a9891ef..abc94f147 100644 --- a/apps/web/src/pages/generate/components/CanvasPreviewGrid.tsx +++ b/apps/web/src/pages/generate/components/CanvasPreviewGrid.tsx @@ -140,7 +140,19 @@ const CanvasPreviewGrid: React.FC = ({ bold: titleSettings.bold, italic: titleSettings.italic, stroke: titleSettings.stroke, + strokeWidth: titleSettings.strokeWidth, + strokeColor: titleSettings.strokeColor, shadow: titleSettings.shadow, + shadowOffsetX: titleSettings.shadowOffsetX, + shadowOffsetY: titleSettings.shadowOffsetY, + shadowBlur: titleSettings.shadowBlur, + shadowColor: titleSettings.shadowColor, + bgEnabled: titleSettings.bgEnabled, + bgColor: titleSettings.bgColor, + bgPadding: titleSettings.bgPadding, + bgRadius: titleSettings.bgRadius, + lineHeight: titleSettings.lineHeight, + maxCharsPerLine: titleSettings.maxCharsPerLine, posX: titleSettings.posX, posY: titleSettings.posY, }} diff --git a/apps/web/src/pages/generate/components/FrontendPreviewPlayer.tsx b/apps/web/src/pages/generate/components/FrontendPreviewPlayer.tsx index 238a68f01..7c7fc126d 100644 --- a/apps/web/src/pages/generate/components/FrontendPreviewPlayer.tsx +++ b/apps/web/src/pages/generate/components/FrontendPreviewPlayer.tsx @@ -36,6 +36,18 @@ interface FrontendPreviewPlayerProps { italic?: boolean stroke?: boolean shadow?: boolean + strokeWidth?: number + strokeColor?: string + shadowOffsetX?: number + shadowOffsetY?: number + shadowBlur?: number + shadowColor?: string + bgEnabled?: boolean + bgColor?: string + bgPadding?: number + bgRadius?: number + lineHeight?: number + maxCharsPerLine?: number posX?: number | null posY?: number | null } @@ -249,10 +261,25 @@ const FrontendPreviewPlayer: React.FC = ({ const titleSidePct = (TITLE_MARGIN_SIDE / playRes.width) * 100 const titleTopPct = (TITLE_MARGIN_TOP / playRes.height) * 100 const titleBottomPct = (TITLE_MARGIN_BOTTOM / playRes.height) * 100 - const titleScale = containerHeight > 0 ? containerHeight / playRes.height : 1 - const titleStrokeWidth = Math.max(1, 2 * titleScale) - const titleShadowBlur = 4 * titleScale - const titleShadowOffset = 2 * titleScale + // 标题缩放到容器:字号 px = (settings.size / playRes.height) * containerHeight + // 描边/阴影:读 titleSettings 真实值,按容器比例缩放 + const titleStrokeWidth = Math.max( + 1, + ((titleSettings?.strokeWidth ?? 4) / playRes.height) * containerHeight, + ) + const titleStrokeColor = titleSettings?.strokeColor ?? "#000000" + const titleShadowBlur = ((titleSettings?.shadowBlur ?? 4) / playRes.height) * containerHeight + const titleShadowOffsetX = + ((titleSettings?.shadowOffsetX ?? 2) / playRes.height) * containerHeight + const titleShadowOffsetY = + ((titleSettings?.shadowOffsetY ?? 2) / playRes.height) * containerHeight + const titleShadowColor = titleSettings?.shadowColor ?? "rgba(0,0,0,0.8)" + const titleShadowStr = `${titleShadowOffsetX}px ${titleShadowOffsetY}px ${titleShadowBlur}px ${titleShadowColor}` + // 标题背景色块 + const titleBgEnabled = !!titleSettings?.bgEnabled + const titleBgColor = titleSettings?.bgColor ?? "rgba(0,0,0,0.5)" + const titleBgPadding = ((titleSettings?.bgPadding ?? 12) / playRes.height) * containerHeight + const titleBgRadius = ((titleSettings?.bgRadius ?? 8) / playRes.height) * containerHeight // ── Video 播放器(默认路径,浏览器原生硬件解码) ── const { @@ -561,14 +588,18 @@ const FrontendPreviewPlayer: React.FC = ({ color: titleSettings.color || "#ffffff", fontWeight: titleSettings.bold ? 700 : 400, fontStyle: titleSettings.italic ? "italic" : "normal", - lineHeight: 1.05, + lineHeight: titleSettings.lineHeight ?? 1.05, wordBreak: "break-word", WebkitTextStroke: titleSettings.stroke - ? `${titleStrokeWidth}px #000000` + ? `${titleStrokeWidth}px ${titleStrokeColor}` : undefined, - textShadow: titleSettings.shadow - ? `${titleShadowOffset}px ${titleShadowOffset}px ${titleShadowBlur}px rgba(0,0,0,0.8)` + textShadow: titleSettings.shadow ? titleShadowStr : undefined, + background: titleBgEnabled ? titleBgColor : undefined, + padding: titleBgEnabled + ? `${titleBgPadding}px ${titleBgPadding * 1.5}px` : undefined, + borderRadius: titleBgEnabled ? `${titleBgRadius}px` : undefined, + display: titleBgEnabled ? "inline-block" : undefined, }} > {(effectiveTitle || "").split(/[//]/).map((part, i) => (