feat(stammbaum): centroid-anchored zoom (zoomAtPoint) (#692)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -81,3 +81,28 @@ export function screenDeltaToSvg(
|
||||
dy: elPxH > 0 ? dyPx * (viewBoxH / elPxH) : 0
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Zoom to `newZoom` while keeping a given anchor point fixed on screen
|
||||
* (pinch-centroid zoom — US-PAN-002 AC1 / US-PAN-003 AC1).
|
||||
*
|
||||
* `anchorX`/`anchorY` are the anchor point expressed as an offset, in SVG units,
|
||||
* from the base viewBox centre. Because the viewBox width scales as `1/z`, the
|
||||
* ratio of old-to-new width is exactly `z / newZoom` independent of the base
|
||||
* size, so the new pan offset that preserves the anchor's screen fraction is
|
||||
* `anchor - (anchor - pan) * (z / newZoom)`.
|
||||
*/
|
||||
export function zoomAtPoint(
|
||||
state: PanZoomState,
|
||||
newZoom: number,
|
||||
anchorX: number,
|
||||
anchorY: number
|
||||
): PanZoomState {
|
||||
const z = clampZoom(newZoom);
|
||||
const ratio = state.z / z;
|
||||
return {
|
||||
x: anchorX - (anchorX - state.x) * ratio,
|
||||
y: anchorY - (anchorY - state.y) * ratio,
|
||||
z
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user