@@ -29,17 +29,31 @@ class DiagramPanZoom {
2929 const mouseDownHandler = this . onMouseDown . bind ( this )
3030 const mouseMoveHandler = this . onMouseMove . bind ( this )
3131 const mouseUpHandler = this . onMouseUp . bind ( this )
32+
33+ // Touch drag events
34+ const touchStartHandler = this . onTouchStart . bind ( this )
35+ const touchMoveHandler = this . onTouchMove . bind ( this )
36+ const touchEndHandler = this . onTouchEnd . bind ( this )
37+
3238 const resizeHandler = this . resetTransform . bind ( this )
3339
3440 this . container . addEventListener ( "mousedown" , mouseDownHandler )
3541 document . addEventListener ( "mousemove" , mouseMoveHandler )
3642 document . addEventListener ( "mouseup" , mouseUpHandler )
43+
44+ this . container . addEventListener ( "touchstart" , touchStartHandler , { passive : false } )
45+ document . addEventListener ( "touchmove" , touchMoveHandler , { passive : false } )
46+ document . addEventListener ( "touchend" , touchEndHandler )
47+
3748 window . addEventListener ( "resize" , resizeHandler )
3849
3950 this . cleanups . push (
4051 ( ) => this . container . removeEventListener ( "mousedown" , mouseDownHandler ) ,
4152 ( ) => document . removeEventListener ( "mousemove" , mouseMoveHandler ) ,
4253 ( ) => document . removeEventListener ( "mouseup" , mouseUpHandler ) ,
54+ ( ) => this . container . removeEventListener ( "touchstart" , touchStartHandler ) ,
55+ ( ) => document . removeEventListener ( "touchmove" , touchMoveHandler ) ,
56+ ( ) => document . removeEventListener ( "touchend" , touchEndHandler ) ,
4357 ( ) => window . removeEventListener ( "resize" , resizeHandler ) ,
4458 )
4559 }
@@ -99,6 +113,30 @@ class DiagramPanZoom {
99113 this . container . style . cursor = "grab"
100114 }
101115
116+ private onTouchStart ( e : TouchEvent ) {
117+ if ( e . touches . length !== 1 ) return
118+ this . isDragging = true
119+ const touch = e . touches [ 0 ]
120+ this . startPan = { x : touch . clientX - this . currentPan . x , y : touch . clientY - this . currentPan . y }
121+ }
122+
123+ private onTouchMove ( e : TouchEvent ) {
124+ if ( ! this . isDragging || e . touches . length !== 1 ) return
125+ e . preventDefault ( ) // Prevent scrolling
126+
127+ const touch = e . touches [ 0 ]
128+ this . currentPan = {
129+ x : touch . clientX - this . startPan . x ,
130+ y : touch . clientY - this . startPan . y ,
131+ }
132+
133+ this . updateTransform ( )
134+ }
135+
136+ private onTouchEnd ( ) {
137+ this . isDragging = false
138+ }
139+
102140 private zoom ( delta : number ) {
103141 const newScale = Math . min ( Math . max ( this . scale + delta , this . MIN_SCALE ) , this . MAX_SCALE )
104142
@@ -120,11 +158,15 @@ class DiagramPanZoom {
120158 }
121159
122160 private resetTransform ( ) {
123- this . scale = 1
124161 const svg = this . content . querySelector ( "svg" ) !
162+ const rect = svg . getBoundingClientRect ( )
163+ const width = rect . width / this . scale
164+ const height = rect . height / this . scale
165+
166+ this . scale = 1
125167 this . currentPan = {
126- x : svg . getBoundingClientRect ( ) . width / 2 ,
127- y : svg . getBoundingClientRect ( ) . height / 2 ,
168+ x : ( this . container . clientWidth - width ) / 2 ,
169+ y : ( this . container . clientHeight - height ) / 2 ,
128170 }
129171 this . updateTransform ( )
130172 }
0 commit comments