@@ -2,6 +2,52 @@ import * as d3 from 'd3';
2
2
import { Application , Container , Graphics , Text } from 'pixi.js' ;
3
3
import { testData } from './TestData' ;
4
4
5
+ interface AnimatedValues {
6
+ zoom : number ;
7
+ zoomX : number ;
8
+ zoomY : number ;
9
+ }
10
+
11
+ class Animator < Key extends string > {
12
+ private values : Record < Key , number > ;
13
+ private targetValues : Record < Key , number > ;
14
+ private durations : Record < Key , number > ;
15
+
16
+ constructor ( initialValues : Record < Key , number > , durations : Record < Key , number > ) {
17
+ this . values = initialValues ;
18
+ this . targetValues = { ... initialValues } ;
19
+ this . durations = durations ;
20
+ }
21
+
22
+ public setTarget ( key : Key , value : number ) {
23
+ this . targetValues [ key ] = value ;
24
+ }
25
+
26
+ public update ( delta : number ) {
27
+ for ( const key in this . values ) {
28
+ this . values [ key ] += ( this . targetValues [ key ] - this . values [ key ] ) * ( 1.0 - Math . exp ( - this . durations [ key ] * delta ) ) ;
29
+ }
30
+ }
31
+
32
+ public get ( key : Key ) {
33
+ return this . values [ key ] ;
34
+ }
35
+
36
+ public isAnimating ( key : Key ) {
37
+ return Math . pow ( this . values [ key ] - this . targetValues [ key ] , 2 ) > 0.0000001 ;
38
+ }
39
+ }
40
+
41
+ const animator = new Animator < keyof AnimatedValues > ( {
42
+ zoom : 1 ,
43
+ zoomX : 0 ,
44
+ zoomY : 0 ,
45
+ } , {
46
+ zoom : 0.3 ,
47
+ zoomX : 0.3 ,
48
+ zoomY : 0.3 ,
49
+ } ) ;
50
+
5
51
const width = 400 ;
6
52
const height = 400 ;
7
53
const element = document . getElementById ( 'graph-mount-point' ) ! ;
@@ -83,18 +129,28 @@ d3.select(app.canvas).call(
83
129
// @ts -ignore
84
130
d3 . zoom ( ) . on ( 'zoom' , ( { transform } : { transform : d3 . ZoomTransform } ) => {
85
131
zoom = transform ;
86
- app . stage . updateTransform ( {
87
- scaleX : transform . k ,
88
- scaleY : transform . k ,
89
- x : transform . x ,
90
- y : transform . y ,
91
- } ) ;
132
+ animator . setTarget ( 'zoom' , transform . k ) ;
133
+ animator . setTarget ( 'zoomX' , transform . x ) ;
134
+ animator . setTarget ( 'zoomY' , transform . y ) ;
92
135
} ) ,
93
136
) ;
94
137
95
- app . ticker . add ( ( ) => {
138
+ app . ticker . add ( ( ticker ) => {
139
+ animator . update ( ticker . deltaTime ) ;
140
+
141
+ if ( animator . isAnimating ( 'zoom' ) || animator . isAnimating ( 'zoomX' ) || animator . isAnimating ( 'zoomY' ) ) {
142
+ console . log ( 'Animating' ) ;
143
+
144
+ app . stage . updateTransform ( {
145
+ scaleX : animator . get ( 'zoom' ) ,
146
+ scaleY : animator . get ( 'zoom' ) ,
147
+ x : animator . get ( 'zoomX' ) ,
148
+ y : animator . get ( 'zoomY' ) ,
149
+ } ) ;
150
+ }
151
+
96
152
for ( const node of simulation . nodes ( ) ) {
97
- node . text ! . scale . set ( 1 / zoom . k ) ;
153
+ node . text ! . scale . set ( 1 / animator . get ( 'zoom' ) ) ;
98
154
node . text ! . position . set ( 0 , 10 ) ;
99
155
}
100
156
@@ -114,7 +170,7 @@ app.ticker.add(() => {
114
170
. fill ( )
115
171
. stroke ( {
116
172
color : 0xffffff ,
117
- width : 1 / zoom . k ,
173
+ width : 1 / animator . get ( 'zoom' ) ,
118
174
} ) ;
119
175
}
120
176
} ) ;
@@ -135,8 +191,8 @@ function dragstarted(event: any) {
135
191
function dragged ( event : any ) {
136
192
if ( ! event . subject ) return ;
137
193
138
- dragX += event . dx / zoom . k ;
139
- dragY += event . dy / zoom . k ;
194
+ dragX += event . dx / animator . get ( 'zoom' ) ;
195
+ dragY += event . dy / animator . get ( 'zoom' ) ;
140
196
141
197
event . subject . fx = dragX ;
142
198
event . subject . fy = dragY ;
@@ -149,3 +205,4 @@ function dragended(event: any) {
149
205
event . subject . fx = null ;
150
206
event . subject . fy = null ;
151
207
}
208
+
0 commit comments