Skip to content

Commit e5a3055

Browse files
committed
refactor(core)!: use xy panzoom instance
chore(changeset): add Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com>
1 parent 4c516f5 commit e5a3055

File tree

18 files changed

+292
-654
lines changed

18 files changed

+292
-654
lines changed

.changeset/tame-books-cross.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@vue-flow/core": major
3+
---
4+
5+
Replace d3 zoom and pan with panzoom instance

packages/core/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@
7373
"@vueuse/core": "^10.5.0",
7474
"d3-drag": "^3.0.0",
7575
"d3-selection": "^3.0.0",
76-
"d3-zoom": "^3.0.0",
7776
"@xyflow/system": "^0.0.36"
7877
},
7978
"devDependencies": {
@@ -82,7 +81,6 @@
8281
"@tooling/tsconfig": "workspace:*",
8382
"@types/d3-drag": "^3.0.4",
8483
"@types/d3-selection": "^3.0.7",
85-
"@types/d3-zoom": "^3.0.5",
8684
"@vitejs/plugin-vue": "^4.4.0",
8785
"autoprefixer": "^10.4.16",
8886
"postcss": "^8.4.31",

packages/core/src/composables/useDrag.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export function useDrag(params: UseDragParams) {
120120
}
121121
}
122122

123-
const autoPan = () => {
123+
const autoPan = async () => {
124124
if (!containerBounds) {
125125
return
126126
}
@@ -133,7 +133,7 @@ export function useDrag(params: UseDragParams) {
133133
y: (lastPos.y ?? 0) - yMovement / viewport.value.zoom,
134134
}
135135

136-
if (panBy({ x: xMovement, y: yMovement })) {
136+
if (await panBy({ x: xMovement, y: yMovement })) {
137137
updateNodes(nextPos)
138138
}
139139
}
Lines changed: 43 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import { zoomIdentity } from 'd3-zoom'
21
import { computed } from 'vue'
3-
import { clampPosition, rendererPointToPoint } from '@xyflow/system'
4-
import type { D3Selection, GraphNode, Project, State, ViewportFunctions } from '../types'
2+
import { rendererPointToPoint } from '@xyflow/system'
3+
import type { GraphNode, Project, State, ViewportFunctions } from '../types'
54
import { getRectOfNodes, getTransformForBounds, pointToRendererPoint, warn } from '../utils'
65

76
export interface ViewportHelper extends ViewportFunctions {
@@ -29,9 +28,7 @@ const initialViewportHelper: ViewportHelper = {
2928
screenToFlowCoordinate: (position) => position,
3029
flowToScreenCoordinate: (position) => position,
3130
setViewport: noop,
32-
setTransform: noop,
3331
getViewport: () => ({ x: 0, y: 0, zoom: 1 }),
34-
getTransform: () => ({ x: 0, y: 0, zoom: 1 }),
3532
viewportInitialized: false,
3633
}
3734

@@ -42,43 +39,9 @@ const initialViewportHelper: ViewportHelper = {
4239
* @param state
4340
*/
4441
export function useViewportHelper(state: State) {
45-
function zoom(scale: number, duration?: number) {
46-
return new Promise<boolean>((resolve) => {
47-
if (state.d3Selection && state.d3Zoom) {
48-
state.d3Zoom.scaleBy(
49-
transition(state.d3Selection, duration, () => {
50-
resolve(true)
51-
}),
52-
scale,
53-
)
54-
} else {
55-
resolve(false)
56-
}
57-
})
58-
}
59-
60-
function transformViewport(x: number, y: number, zoom: number, duration?: number) {
61-
return new Promise<boolean>((resolve) => {
62-
// enforce translate extent
63-
const { x: clampedX, y: clampedY } = clampPosition({ x: -x, y: -y }, state.translateExtent)
64-
65-
const nextTransform = zoomIdentity.translate(-clampedX, -clampedY).scale(zoom)
66-
67-
if (state.d3Selection && state.d3Zoom) {
68-
state.d3Zoom.transform(
69-
transition(state.d3Selection, duration, () => {
70-
resolve(true)
71-
}),
72-
nextTransform,
73-
)
74-
} else {
75-
resolve(false)
76-
}
77-
})
78-
}
79-
8042
return computed<ViewportHelper>(() => {
81-
const isInitialized = state.d3Zoom && state.d3Selection && state.dimensions.width && state.dimensions.height
43+
const panZoom = state.panZoom
44+
const isInitialized = state.panZoom && state.dimensions.width && state.dimensions.height
8245

8346
if (!isInitialized) {
8447
return initialViewportHelper
@@ -88,44 +51,36 @@ export function useViewportHelper(state: State) {
8851
viewportInitialized: true,
8952
// todo: allow passing scale as option
9053
zoomIn: (options) => {
91-
return zoom(1.2, options?.duration)
54+
return panZoom ? panZoom.scaleBy(1.2, options) : Promise.resolve(false)
9255
},
9356
zoomOut: (options) => {
94-
return zoom(1 / 1.2, options?.duration)
57+
return panZoom ? panZoom.scaleBy(1 / 1.2, options) : Promise.resolve(false)
9558
},
9659
zoomTo: (zoomLevel, options) => {
97-
return new Promise<boolean>((resolve) => {
98-
if (state.d3Selection && state.d3Zoom) {
99-
state.d3Zoom.scaleTo(
100-
transition(state.d3Selection, options?.duration, () => {
101-
resolve(true)
102-
}),
103-
zoomLevel,
104-
)
105-
} else {
106-
resolve(false)
107-
}
108-
})
109-
},
110-
setViewport: (transform, options) => {
111-
return transformViewport(transform.x, transform.y, transform.zoom, options?.duration)
60+
return panZoom ? panZoom.scaleTo(zoomLevel, options) : Promise.resolve(false)
11261
},
113-
setTransform: (transform, options) => {
114-
return transformViewport(transform.x, transform.y, transform.zoom, options?.duration)
62+
setViewport: async (viewport, options) => {
63+
if (!panZoom) {
64+
return Promise.resolve(false)
65+
}
66+
67+
await panZoom.setViewport(
68+
{
69+
x: viewport.x ?? state.viewport.x,
70+
y: viewport.y ?? state.viewport.y,
71+
zoom: viewport.zoom ?? state.viewport.zoom,
72+
},
73+
options,
74+
)
75+
76+
return Promise.resolve(true)
11577
},
11678
getViewport: () => ({
11779
x: state.viewport.x,
11880
y: state.viewport.y,
11981
zoom: state.viewport.zoom,
12082
}),
121-
getTransform: () => {
122-
return {
123-
x: state.viewport.x,
124-
y: state.viewport.y,
125-
zoom: state.viewport.zoom,
126-
}
127-
},
128-
fitView: (
83+
fitView: async (
12984
options = {
13085
padding: DEFAULT_PADDING,
13186
includeHiddenNodes: false,
@@ -143,7 +98,7 @@ export function useViewportHelper(state: State) {
14398
}
14499
}
145100

146-
if (!nodesToFit.length) {
101+
if (!nodesToFit.length || !panZoom) {
147102
return Promise.resolve(false)
148103
}
149104

@@ -159,16 +114,28 @@ export function useViewportHelper(state: State) {
159114
options.offset,
160115
)
161116

162-
return transformViewport(x, y, zoom, options?.duration)
117+
await panZoom.setViewport({ x, y, zoom }, options)
118+
119+
return Promise.resolve(true)
163120
},
164-
setCenter: (x, y, options) => {
121+
setCenter: async (x, y, options) => {
122+
if (!panZoom) {
123+
return Promise.resolve(false)
124+
}
125+
165126
const nextZoom = typeof options?.zoom !== 'undefined' ? options.zoom : state.maxZoom
166127
const centerX = state.dimensions.width / 2 - x * nextZoom
167128
const centerY = state.dimensions.height / 2 - y * nextZoom
168129

169-
return transformViewport(centerX, centerY, nextZoom, options?.duration)
130+
await panZoom.setViewport({ x: centerX, y: centerY, zoom: nextZoom }, options)
131+
132+
return Promise.resolve(true)
170133
},
171-
fitBounds: (bounds, options = { padding: DEFAULT_PADDING }) => {
134+
fitBounds: async (bounds, options = { padding: DEFAULT_PADDING }) => {
135+
if (!panZoom) {
136+
return Promise.resolve(false)
137+
}
138+
172139
const { x, y, zoom } = getTransformForBounds(
173140
bounds,
174141
state.dimensions.width,
@@ -178,7 +145,9 @@ export function useViewportHelper(state: State) {
178145
options.padding,
179146
)
180147

181-
return transformViewport(x, y, zoom, options?.duration)
148+
await panZoom.setViewport({ x, y, zoom }, options)
149+
150+
return Promise.resolve(true)
182151
},
183152
project: (position) => pointToRendererPoint(position, state.viewport, state.snapToGrid, state.snapGrid),
184153
screenToFlowCoordinate: (position) => {
@@ -212,7 +181,3 @@ export function useViewportHelper(state: State) {
212181
}
213182
})
214183
}
215-
216-
function transition(selection: D3Selection, ms = 0, onEnd: () => void) {
217-
return (selection as any).transition().duration(ms).on('end', onEnd)
218-
}

packages/core/src/container/Viewport/Transform.vue

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)