feat(stammbaum): drive viewBox from PanZoomState (pan + zoom) (#692)
Replace the scalar zoom prop with a {x,y,z} PanZoomState. The viewBox centre
is offset by the pan and width/height scaled by zoom; the default {0,0,1}
frames the whole tree (fit-to-screen). Page header buttons now step view.z
through clampZoom over the resolved 0.25–3.0 range.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
ROW_GAP,
|
||||
type Layout
|
||||
} from '$lib/person/genealogy/layout/buildLayout';
|
||||
import type { PanZoomState } from '$lib/person/genealogy/panZoom';
|
||||
|
||||
type PersonNodeDTO = components['schemas']['PersonNodeDTO'];
|
||||
type RelationshipDTO = components['schemas']['RelationshipDTO'];
|
||||
@@ -16,7 +17,7 @@ interface Props {
|
||||
nodes: PersonNodeDTO[];
|
||||
edges: RelationshipDTO[];
|
||||
selectedId: string | null;
|
||||
zoom: number;
|
||||
panZoom: PanZoomState;
|
||||
onSelect: (id: string) => void;
|
||||
/**
|
||||
* Force-show or force-hide the generation gutter. When undefined, falls
|
||||
@@ -27,7 +28,7 @@ interface Props {
|
||||
showGutter?: boolean;
|
||||
}
|
||||
|
||||
let { nodes, edges, selectedId, zoom, onSelect, showGutter }: Props = $props();
|
||||
let { nodes, edges, selectedId, panZoom, onSelect, showGutter }: Props = $props();
|
||||
|
||||
const layout = $derived.by<Layout>(() => buildLayout(nodes, edges));
|
||||
|
||||
@@ -79,12 +80,20 @@ const gutterRows = $derived.by<GutterRow[]>(() => {
|
||||
return rows;
|
||||
});
|
||||
|
||||
// Base viewBox geometry at z=1, no pan — the whole tree framed (#692). Pan
|
||||
// offsets shift the centre; zoom scales width/height inversely. The default
|
||||
// {x:0,y:0,z:1} therefore fits the tree to the element (fit-to-screen).
|
||||
const baseDims = $derived({ w: layout.viewW + gutterWidth, h: layout.viewH });
|
||||
const baseCentre = $derived({
|
||||
x: layout.viewX - gutterWidth + baseDims.w / 2,
|
||||
y: layout.viewY + layout.viewH / 2
|
||||
});
|
||||
|
||||
const viewBox = $derived.by(() => {
|
||||
const totalW = layout.viewW + gutterWidth;
|
||||
const w = totalW / zoom;
|
||||
const h = layout.viewH / zoom;
|
||||
const cx = layout.viewX - gutterWidth + totalW / 2;
|
||||
const cy = layout.viewY + layout.viewH / 2;
|
||||
const w = baseDims.w / panZoom.z;
|
||||
const h = baseDims.h / panZoom.z;
|
||||
const cx = baseCentre.x + panZoom.x;
|
||||
const cy = baseCentre.y + panZoom.y;
|
||||
return `${cx - w / 2} ${cy - h / 2} ${w} ${h}`;
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user