1- import { zoomIdentity } from 'd3-zoom'
21import { 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'
54import { getRectOfNodes , getTransformForBounds , pointToRendererPoint , warn } from '../utils'
65
76export 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 */
4441export 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- }
0 commit comments