fix(title): 选模板后视频预览标题正确应用全部样式字段 #2019

Merged
xiaoxia merged 3 commits from fix/template-preview-stroke-shadow into develop 2026-09-23 14:54:58 +08:00
4 changed files with 64 additions and 9 deletions
@@ -580,7 +580,19 @@ const GeneratePage: 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,
}}
@@ -140,7 +140,19 @@ const CanvasPreviewGrid: React.FC<CanvasPreviewGridProps> = ({
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,
}}
@@ -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<FrontendPreviewPlayerProps> = ({
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<FrontendPreviewPlayerProps> = ({
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) => (
@@ -190,7 +190,7 @@ const TitleMiniPreview: React.FC<Props> = ({
ctx.shadowBlur = prevShadow.b
ctx.shadowOffsetX = prevShadow.ox
ctx.shadowOffsetY = prevShadow.oy
}, [settings, width, h, text])
}, [settings, width, h, text, transparent, portrait, background])
return (
<canvas