@@ -45,7 +45,8 @@ export default class ViewController {
45
45
graph . translate ( viewCenter . x - groupCenter . x , viewCenter . y - groupCenter . y , animate , animateCfg ) ;
46
46
}
47
47
48
- private animatedFitView ( group : IGroup , startMatrix : number [ ] , animateCfg : GraphAnimateConfig , bbox : BBox , viewCenter : Point , groupCenter : Point , ratio : number ) : void {
48
+ private animatedFitView ( group : IGroup , startMatrix : number [ ] , animateCfg : GraphAnimateConfig , bbox : BBox , viewCenter : Point , groupCenter : Point ,
49
+ ratio : number , zoomToFit : boolean ) : void {
49
50
const { graph } = this ;
50
51
animateCfg = animateCfg ? animateCfg : { duration : 500 , easing : 'easeCubic' } ;
51
52
@@ -58,6 +59,20 @@ export default class ViewController {
58
59
if ( isNaN ( vx ) || isNaN ( vy ) ) return ;
59
60
const translatedMatrix = transform ( matrix , [ [ 't' , vx , vy ] ] ) ;
60
61
62
+ if ( ! zoomToFit ) {
63
+ // If zooming is not needed just animate the current translated matrix and return
64
+ const animationConfig = getAnimateCfgWithCallback ( {
65
+ animateCfg,
66
+ callback : ( ) => {
67
+ graph . emit ( 'viewportchange' , { action : 'translate' , matrix : translatedMatrix } ) ;
68
+ }
69
+ } ) ;
70
+ group . animate ( ( ratio : number ) => {
71
+ return { matrix : lerpArray ( startMatrix , translatedMatrix , ratio ) } ;
72
+ } , animationConfig ) ;
73
+ return ;
74
+ }
75
+
61
76
// Zoom
62
77
const minZoom : number = graph . get ( 'minZoom' ) ;
63
78
const maxZoom : number = graph . get ( 'maxZoom' ) ;
@@ -67,7 +82,7 @@ export default class ViewController {
67
82
realRatio = minZoom ;
68
83
console . warn ( 'fitview failed, ratio out of range, ratio: %f' , ratio , 'graph minzoom has been used instead' ) ;
69
84
} else if ( maxZoom && ratio > maxZoom ) {
70
- realRatio = minZoom ;
85
+ realRatio = maxZoom ;
71
86
console . warn ( 'fitview failed, ratio out of range, ratio: %f' , ratio , 'graph maxzoom has been used instead' ) ;
72
87
}
73
88
let zoomedMatrix = transform ( translatedMatrix , [
@@ -120,7 +135,7 @@ export default class ViewController {
120
135
}
121
136
122
137
if ( animate ) {
123
- this . animatedFitView ( group , startMatrix , animateCfg , bbox , viewCenter , groupCenter , ratio ) ;
138
+ this . animatedFitView ( group , startMatrix , animateCfg , bbox , viewCenter , groupCenter , ratio , true ) ;
124
139
} else {
125
140
const dx = viewCenter . x - groupCenter . x ;
126
141
const dy = viewCenter . y - groupCenter . y ;
@@ -175,7 +190,7 @@ export default class ViewController {
175
190
}
176
191
177
192
if ( animate ) {
178
- this . animatedFitView ( group , startMatrix , animateCfg , bbox , viewCenter , groupCenter , ratio ) ;
193
+ this . animatedFitView ( group , startMatrix , animateCfg , bbox , viewCenter , groupCenter , ratio , true ) ;
179
194
} else {
180
195
const initZoomRatio = graph . getZoom ( ) ;
181
196
let endZoom = initZoomRatio * ratio ;
@@ -316,6 +331,72 @@ export default class ViewController {
316
331
}
317
332
}
318
333
334
+ public focusItems ( items : Item [ ] , zoomToFit : boolean , animate ?: boolean , animateCfg ?: GraphAnimateConfig ) : void {
335
+ if ( ! items . length ) {
336
+ return ;
337
+ }
338
+
339
+ const { graph } = this ;
340
+ const padding = this . getFormatPadding ( ) ;
341
+ const width : number = graph . get ( 'width' ) ;
342
+ const height : number = graph . get ( 'height' ) ;
343
+ const group : IGroup = graph . get ( 'group' ) ;
344
+ const startMatrix = group . getMatrix ( ) || [ 1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 ] ;
345
+ group . resetMatrix ( ) ;
346
+
347
+ let bbox : BBox = {
348
+ x : 0 , y : 0 ,
349
+ minX : Number . MAX_SAFE_INTEGER , minY : Number . MAX_SAFE_INTEGER ,
350
+ maxX : Number . MIN_SAFE_INTEGER , maxY : Number . MIN_SAFE_INTEGER ,
351
+ width : 0 , height : 0
352
+ } ;
353
+ for ( const item of items ) {
354
+ const itemBBox = item . getBBox ( ) ;
355
+ if ( itemBBox . minX < bbox . minX ) {
356
+ bbox . minX = itemBBox . minX ;
357
+ }
358
+ if ( itemBBox . minY < bbox . minY ) {
359
+ bbox . minY = itemBBox . minY ;
360
+ }
361
+ if ( itemBBox . maxX > bbox . maxX ) {
362
+ bbox . maxX = itemBBox . maxX ;
363
+ }
364
+ if ( itemBBox . maxY > bbox . maxY ) {
365
+ bbox . maxY = itemBBox . maxY ;
366
+ }
367
+ }
368
+ bbox . x = bbox . minX ;
369
+ bbox . y = bbox . minY ;
370
+ bbox . width = bbox . maxX - bbox . minX ;
371
+ bbox . height = bbox . maxY - bbox . minY ;
372
+
373
+ if ( bbox . width === 0 || bbox . height === 0 ) return ;
374
+ const viewCenter = this . getViewCenter ( ) ;
375
+
376
+ const groupCenter : Point = {
377
+ x : bbox . x + bbox . width / 2 ,
378
+ y : bbox . y + bbox . height / 2 ,
379
+ } ;
380
+
381
+ // Compute ratio
382
+ const w = ( width - padding [ 1 ] - padding [ 3 ] ) / bbox . width ;
383
+ const h = ( height - padding [ 0 ] - padding [ 2 ] ) / bbox . height ;
384
+ let ratio = w ;
385
+ if ( w > h ) {
386
+ ratio = h ;
387
+ }
388
+
389
+ if ( animate ) {
390
+ this . animatedFitView ( group , startMatrix , animateCfg , bbox , viewCenter , groupCenter , ratio , zoomToFit ) ;
391
+ } else {
392
+ graph . translate ( viewCenter . x - groupCenter . x , viewCenter . y - groupCenter . y ) ;
393
+
394
+ if ( zoomToFit && ! graph . zoom ( ratio , viewCenter ) ) {
395
+ console . warn ( 'zoom failed, ratio out of range, ratio: %f' , ratio ) ;
396
+ }
397
+ }
398
+ }
399
+
319
400
/**
320
401
* 改变 canvas 画布的宽度和高度
321
402
* @param width canvas 宽度
0 commit comments