feat(react/svelte): controlled viewport (#3461)

* feat(react): controlled viewport

* refactor(react): cleanup viewport

* feat(svelte): two way data binding for viewport, cleanup transform <> viewport stuff

* refactor(svelte): viewport stuff
This commit is contained in:
Moritz Klack
2023-09-28 16:19:03 +02:00
committed by GitHub
parent 2215b68438
commit ae33cba887
35 changed files with 351 additions and 95 deletions
+3 -2
View File
@@ -1,6 +1,6 @@
import { ZoomTransform } from 'd3-zoom';
import type { ZoomTransform } from 'd3-zoom';
import { CoordinateExtent, PanOnScrollMode, Transform, Viewport } from './';
import { PanOnScrollMode, type CoordinateExtent, type Transform, type Viewport } from './';
export type OnDraggingChange = (dragging: boolean) => void;
export type OnTransformChange = (transform: Transform) => void;
@@ -55,4 +55,5 @@ export type PanZoomInstance = {
setTranslateExtent: (translateExtent: CoordinateExtent) => void;
scaleTo: (scale: number, options?: PanZoomTransformOptions) => void;
scaleBy: (factor: number, options?: PanZoomTransformOptions) => void;
syncViewport: (viewport: Viewport) => void;
};
@@ -194,6 +194,22 @@ export function XYPanZoom({
return nextTransform;
}
function syncViewport(viewport: Viewport) {
if (d3Selection) {
const nextTransform = viewportToTransform(viewport);
const currentTransform = d3Selection.property('__zoom');
if (
currentTransform.k !== viewport.zoom ||
currentTransform.x !== viewport.x ||
currentTransform.y !== viewport.y
) {
// @ts-ignore
d3ZoomInstance?.transform(d3Selection, nextTransform, null, { sync: true });
}
}
}
function getViewport(): Viewport {
const transform = d3Selection ? zoomTransform(d3Selection.node() as Element) : { x: 0, y: 0, k: 1 };
return { x: transform.x, y: transform.y, zoom: transform.k };
@@ -229,5 +245,6 @@ export function XYPanZoom({
scaleBy,
setScaleExtent,
setTranslateExtent,
syncViewport,
};
}
@@ -183,7 +183,9 @@ export function createPanZoomHandler({
onPaneContextMenu && isRightClickPan(panOnDrag, zoomPanValues.mouseButton ?? 0)
);
onTransformChange([event.transform.x, event.transform.y, event.transform.k]);
if (!event.sourceEvent?.sync) {
onTransformChange([event.transform.x, event.transform.y, event.transform.k]);
}
if (onPanZoom && !event.sourceEvent?.internal) {
onPanZoom?.(event.sourceEvent as MouseEvent | TouchEvent, transformToViewport(event.transform));