feat(wm): GPS watermark color + place-name/time toggles, "commune, city" locality
This commit is contained in:
@@ -108,7 +108,7 @@ interface ViewfinderProps {
|
||||
// GPS mark placement (WATERMARK tab drag + pinch): the same 0..1 fractions
|
||||
// of the same area customWm uses, TOP-LEFT anchored; size multiplies the
|
||||
// base 3.2%-of-width size. Absent = the historical fixed top-left look.
|
||||
gpsWm?: { x: number; y: number; size: number };
|
||||
gpsWm?: { x: number; y: number; size: number; color?: string; showName?: boolean; showTime?: boolean };
|
||||
onGpsWmChange?: (x: number, y: number, size: number) => void;
|
||||
// Pinch on the custom mark: its SIZE, exactly like the panel's SIZE chip.
|
||||
onWmSizeChange?: (size: number) => void;
|
||||
@@ -1720,25 +1720,32 @@ const Viewfinder = forwardRef<ViewfinderHandle, ViewfinderProps>(function Viewfi
|
||||
const pad = (n: number) => String(n).padStart(2, '0');
|
||||
const timestampStr = `${pad(d.getDate())}/${pad(d.getMonth() + 1)}/${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
||||
|
||||
// TOP-LEFT anchored two-line block at the dragged fraction of the same area
|
||||
// the custom mark uses (frame card / photo window / screen). A framed
|
||||
// export's canvas IS that frame, so the fractions carry straight to the
|
||||
// burn-in — exportEngine step 8 draws with the identical formula.
|
||||
// TOP-LEFT anchored block at the dragged fraction of the same area the
|
||||
// custom mark uses (frame card / photo window / screen). A framed export's
|
||||
// canvas IS that frame, so the fractions carry straight to the burn-in -
|
||||
// exportEngine step 8 draws with the identical formula. Each enabled line
|
||||
// (place name / shot time) stacks under the previous one.
|
||||
const lines: { icon: string; text: string }[] = [];
|
||||
if (gpsWm?.showName !== false) lines.push({ icon: '📍', text: locationName });
|
||||
if (gpsWm?.showTime !== false) lines.push({ icon: '📷', text: timestampStr });
|
||||
if (!lines.length) return null;
|
||||
|
||||
const { ax, ay, iconSize } = gpsAnchor();
|
||||
const row1Y = ay + Math.round(iconSize * 1.1);
|
||||
const row2Y = ay + Math.round(iconSize * 2.3);
|
||||
const textColor = gpsWm?.color ?? '#f59e0b';
|
||||
// One clear space (0.6em ~ a mono space) between each icon and its text.
|
||||
const gap = (w: number) => Math.round(Math.max(w, iconSize) + iconSize * 0.6);
|
||||
const pinW = gpsIconFont.measureText('📍');
|
||||
const camW = gpsIconFont.measureText('📷');
|
||||
// The old fixed row1/row2 spacing, generalised to N rows.
|
||||
const rowY = (i: number) => ay + Math.round(iconSize * (1.1 + i * 1.2));
|
||||
|
||||
return (
|
||||
<Group origin={{ x: ax, y: ay }} transform={wmRotation ? [{ rotate: wmRad }] : undefined}>
|
||||
{/* Icons white so they read as glyphs, not part of the amber text */}
|
||||
<SkiaText x={ax} y={row1Y} text="📍" font={gpsIconFont} color="#ffffff" />
|
||||
<SkiaText x={ax + gap(pinW.width)} y={row1Y} text={locationName} font={gpsFont} color="#f59e0b" />
|
||||
<SkiaText x={ax} y={row2Y} text="📷" font={gpsIconFont} color="#ffffff" />
|
||||
<SkiaText x={ax + gap(camW.width)} y={row2Y} text={timestampStr} font={gpsFont} color="#f59e0b" />
|
||||
{lines.map((line, i) => (
|
||||
<React.Fragment key={line.icon}>
|
||||
{/* Icons white so they read as glyphs, not part of the coloured text */}
|
||||
<SkiaText x={ax} y={rowY(i)} text={line.icon} font={gpsIconFont} color="#ffffff" />
|
||||
<SkiaText x={ax + gap(gpsIconFont.measureText(line.icon).width)} y={rowY(i)} text={line.text} font={gpsFont} color={textColor} />
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Group>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user