fix: scale detail overlay with canvas zoom
This commit is contained in:
parent
409770d386
commit
ac02644d3f
@ -66,9 +66,12 @@ function resolveOverlayText(
|
||||
function renderOverlayComponentContent(
|
||||
snapshot: DetailUiScreenOverlaySnapshot,
|
||||
component: RenderableOverlayComponent,
|
||||
scale: number,
|
||||
) {
|
||||
const content = resolveOverlayText(snapshot, component);
|
||||
const lines = content.split("\n").filter(Boolean);
|
||||
const iconSize = Math.max(12, Math.round(16 * scale));
|
||||
const smallIconSize = Math.max(10, Math.round(14 * scale));
|
||||
|
||||
if (component.type === "detail_feature_card") {
|
||||
const headline = lines[0] || content;
|
||||
@ -77,7 +80,7 @@ function renderOverlayComponentContent(
|
||||
<div className="flex h-full w-full flex-col justify-between">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="mt-0.5 rounded-2xl bg-white/70 p-2 text-blue-600">
|
||||
<Sparkles className="h-4 w-4" />
|
||||
<Sparkles style={{ width: iconSize, height: iconSize }} />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="text-[0.95em] font-extrabold leading-[1.2]">{headline}</div>
|
||||
@ -95,7 +98,7 @@ function renderOverlayComponentContent(
|
||||
if (component.type === "detail_feature_tag") {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center gap-1 whitespace-nowrap">
|
||||
<Sparkles className="h-3.5 w-3.5" />
|
||||
<Sparkles style={{ width: smallIconSize, height: smallIconSize }} />
|
||||
<span>{content}</span>
|
||||
</div>
|
||||
);
|
||||
@ -120,7 +123,7 @@ function renderOverlayComponentContent(
|
||||
if (component.type === "detail_proof_bar") {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center gap-3">
|
||||
<ShieldCheck className="h-4.5 w-4.5 shrink-0" />
|
||||
<ShieldCheck style={{ width: iconSize, height: iconSize }} className="shrink-0" />
|
||||
<div className="min-w-0 text-[0.86em] font-semibold leading-[1.2]">{content}</div>
|
||||
</div>
|
||||
);
|
||||
@ -130,7 +133,7 @@ function renderOverlayComponentContent(
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center gap-2 whitespace-nowrap">
|
||||
<span>{content}</span>
|
||||
<ArrowRight className="h-4.5 w-4.5" />
|
||||
<ArrowRight style={{ width: iconSize, height: iconSize }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -139,7 +142,9 @@ function renderOverlayComponentContent(
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-between gap-3">
|
||||
<div className="min-w-0 text-[0.82em] font-semibold leading-[1.25]">{content}</div>
|
||||
{component.type === "detail_cta_banner" ? <CheckCircle2 className="h-4.5 w-4.5 shrink-0" /> : null}
|
||||
{component.type === "detail_cta_banner" ? (
|
||||
<CheckCircle2 style={{ width: iconSize, height: iconSize }} className="shrink-0" />
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -151,6 +156,7 @@ function getOverlayComponentStyle(params: {
|
||||
component: RenderableOverlayComponent;
|
||||
snapshot: DetailUiScreenOverlaySnapshot;
|
||||
content: string;
|
||||
scale: number;
|
||||
frameOverride?: {
|
||||
x: number;
|
||||
y: number;
|
||||
@ -167,6 +173,7 @@ function getOverlayComponentStyle(params: {
|
||||
const style = (params.component.style || {}) as Record<string, unknown>;
|
||||
const widthScale = 100 / Math.max(1, params.snapshot.screenSize.width);
|
||||
const heightScale = 100 / Math.max(1, params.snapshot.screenSize.height);
|
||||
const scale = Math.max(0.55, Math.min(2.4, params.scale));
|
||||
|
||||
const overlayStyle: CSSProperties = {
|
||||
position: "absolute",
|
||||
@ -175,12 +182,15 @@ function getOverlayComponentStyle(params: {
|
||||
width: `${Number(frame.width || 0) * widthScale}%`,
|
||||
height: `${Number(frame.height || 0) * heightScale}%`,
|
||||
zIndex: Number(params.component.layout?.zIndex || 1),
|
||||
fontSize: typeof style.fontSize === "number" ? `${style.fontSize}px` : undefined,
|
||||
fontSize:
|
||||
typeof style.fontSize === "number" ? `${style.fontSize * scale}px` : undefined,
|
||||
fontFamily: typeof style.fontFamily === "string" ? style.fontFamily : undefined,
|
||||
fontWeight: typeof style.fontWeight === "string" ? style.fontWeight : undefined,
|
||||
lineHeight: typeof style.lineHeight === "number" ? style.lineHeight : undefined,
|
||||
letterSpacing:
|
||||
typeof style.letterSpacing === "number" ? `${style.letterSpacing}px` : undefined,
|
||||
typeof style.letterSpacing === "number"
|
||||
? `${style.letterSpacing * scale}px`
|
||||
: undefined,
|
||||
color: typeof style.color === "string" ? style.color : undefined,
|
||||
textAlign:
|
||||
style.textAlign === "center" || style.textAlign === "right"
|
||||
@ -195,17 +205,26 @@ function getOverlayComponentStyle(params: {
|
||||
background: typeof style.backgroundColor === "string" ? style.backgroundColor : undefined,
|
||||
borderColor: typeof style.borderColor === "string" ? style.borderColor : undefined,
|
||||
borderWidth:
|
||||
typeof style.borderWidth === "number" ? `${style.borderWidth}px` : undefined,
|
||||
typeof style.borderWidth === "number"
|
||||
? `${Math.max(1, style.borderWidth * scale)}px`
|
||||
: undefined,
|
||||
borderStyle:
|
||||
typeof style.borderWidth === "number" && style.borderWidth > 0 ? "solid" : undefined,
|
||||
borderRadius:
|
||||
typeof style.borderRadius === "number" ? `${style.borderRadius}px` : undefined,
|
||||
padding: typeof style.padding === "number" ? `${style.padding}px` : undefined,
|
||||
typeof style.borderRadius === "number"
|
||||
? `${style.borderRadius * scale}px`
|
||||
: undefined,
|
||||
padding:
|
||||
typeof style.padding === "number" ? `${style.padding * scale}px` : undefined,
|
||||
boxShadow: typeof style.boxShadow === "string" ? style.boxShadow : undefined,
|
||||
backdropFilter:
|
||||
typeof style.backdropBlur === "number" ? `blur(${style.backdropBlur}px)` : undefined,
|
||||
typeof style.backdropBlur === "number"
|
||||
? `blur(${style.backdropBlur * scale}px)`
|
||||
: undefined,
|
||||
WebkitBackdropFilter:
|
||||
typeof style.backdropBlur === "number" ? `blur(${style.backdropBlur}px)` : undefined,
|
||||
typeof style.backdropBlur === "number"
|
||||
? `blur(${style.backdropBlur * scale}px)`
|
||||
: undefined,
|
||||
overflow: "hidden",
|
||||
whiteSpace: "pre-wrap",
|
||||
wordBreak: "break-word",
|
||||
@ -467,6 +486,10 @@ export function DetailSurfaceOverlayRenderer(params: {
|
||||
params.imageMetrics && params.imageMetrics.renderedHeight > 0
|
||||
? params.imageMetrics.renderedHeight
|
||||
: params.overlay.screenSize.height;
|
||||
const overlayScale = Math.min(
|
||||
overlayWidth / Math.max(1, params.overlay.screenSize.width),
|
||||
overlayHeight / Math.max(1, params.overlay.screenSize.height),
|
||||
);
|
||||
const frameOverrides = buildFrameOverrides({
|
||||
overlay: params.overlay,
|
||||
components,
|
||||
@ -508,6 +531,7 @@ export function DetailSurfaceOverlayRenderer(params: {
|
||||
component,
|
||||
snapshot: params.overlay!,
|
||||
content,
|
||||
scale: overlayScale,
|
||||
frameOverride: (() => {
|
||||
const frame = frameOverrides.get(component.id);
|
||||
if (!frame) return undefined;
|
||||
@ -520,7 +544,7 @@ export function DetailSurfaceOverlayRenderer(params: {
|
||||
})(),
|
||||
})}
|
||||
>
|
||||
{renderOverlayComponentContent(params.overlay!, component)}
|
||||
{renderOverlayComponentContent(params.overlay!, component, overlayScale)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user