UNPKG

4.73 kBJavaScriptView Raw
1import * as util from './util';
2import * as is from './is';
3import Promise from './promise';
4
5let Animation = function( target, opts, opts2 ){
6 let isCore = is.core(target);
7 let isEle = !isCore;
8
9 let _p = this._private = util.extend( {
10 duration: 1000
11 }, opts, opts2 );
12
13 _p.target = target;
14 _p.style = _p.style || _p.css;
15 _p.started = false;
16 _p.playing = false;
17 _p.hooked = false;
18 _p.applying = false;
19 _p.progress = 0;
20 _p.completes = [];
21 _p.frames = [];
22
23 if( _p.complete && is.fn( _p.complete ) ){
24 _p.completes.push( _p.complete );
25 }
26
27 if( isEle ){
28 let pos = target.position();
29
30 _p.startPosition = _p.startPosition || {
31 x: pos.x,
32 y: pos.y
33 };
34
35 _p.startStyle = _p.startStyle || target.cy().style().getAnimationStartStyle( target, _p.style );
36 }
37
38 if( isCore ){
39 let pan = target.pan();
40
41 _p.startPan = {
42 x: pan.x,
43 y: pan.y
44 };
45
46 _p.startZoom = target.zoom();
47 }
48
49 // for future timeline/animations impl
50 this.length = 1;
51 this[0] = this;
52};
53
54let anifn = Animation.prototype;
55
56util.extend( anifn, {
57
58 instanceString: function(){ return 'animation'; },
59
60 hook: function(){
61 let _p = this._private;
62
63 if( !_p.hooked ){
64 // add to target's animation queue
65 let q;
66 let tAni = _p.target._private.animation;
67 if( _p.queue ){
68 q = tAni.queue;
69 } else {
70 q = tAni.current;
71 }
72 q.push( this );
73
74 // add to the animation loop pool
75 if( is.elementOrCollection( _p.target ) ){
76 _p.target.cy().addToAnimationPool( _p.target );
77 }
78
79 _p.hooked = true;
80 }
81
82 return this;
83 },
84
85 play: function(){
86 let _p = this._private;
87
88 // autorewind
89 if( _p.progress === 1 ){
90 _p.progress = 0;
91 }
92
93 _p.playing = true;
94 _p.started = false; // needs to be started by animation loop
95 _p.stopped = false;
96
97 this.hook();
98
99 // the animation loop will start the animation...
100
101 return this;
102 },
103
104 playing: function(){
105 return this._private.playing;
106 },
107
108 apply: function(){
109 let _p = this._private;
110
111 _p.applying = true;
112 _p.started = false; // needs to be started by animation loop
113 _p.stopped = false;
114
115 this.hook();
116
117 // the animation loop will apply the animation at this progress
118
119 return this;
120 },
121
122 applying: function(){
123 return this._private.applying;
124 },
125
126 pause: function(){
127 let _p = this._private;
128
129 _p.playing = false;
130 _p.started = false;
131
132 return this;
133 },
134
135 stop: function(){
136 let _p = this._private;
137
138 _p.playing = false;
139 _p.started = false;
140 _p.stopped = true; // to be removed from animation queues
141
142 return this;
143 },
144
145 rewind: function(){
146 return this.progress( 0 );
147 },
148
149 fastforward: function(){
150 return this.progress( 1 );
151 },
152
153 time: function( t ){
154 let _p = this._private;
155
156 if( t === undefined ){
157 return _p.progress * _p.duration;
158 } else {
159 return this.progress( t / _p.duration );
160 }
161 },
162
163 progress: function( p ){
164 let _p = this._private;
165 let wasPlaying = _p.playing;
166
167 if( p === undefined ){
168 return _p.progress;
169 } else {
170 if( wasPlaying ){
171 this.pause();
172 }
173
174 _p.progress = p;
175 _p.started = false;
176
177 if( wasPlaying ){
178 this.play();
179 }
180 }
181
182 return this;
183 },
184
185 completed: function(){
186 return this._private.progress === 1;
187 },
188
189 reverse: function(){
190 let _p = this._private;
191 let wasPlaying = _p.playing;
192
193 if( wasPlaying ){
194 this.pause();
195 }
196
197 _p.progress = 1 - _p.progress;
198 _p.started = false;
199
200 let swap = function( a, b ){
201 let _pa = _p[ a ];
202
203 if( _pa == null ){ return; }
204
205 _p[ a ] = _p[ b ];
206 _p[ b ] = _pa;
207 };
208
209 swap( 'zoom', 'startZoom' );
210 swap( 'pan', 'startPan' );
211 swap( 'position', 'startPosition' );
212
213 // swap styles
214 if( _p.style ){
215 for( let i = 0; i < _p.style.length; i++ ){
216 let prop = _p.style[ i ];
217 let name = prop.name;
218 let startStyleProp = _p.startStyle[ name ];
219
220 _p.startStyle[ name ] = prop;
221 _p.style[ i ] = startStyleProp;
222 }
223 }
224
225 if( wasPlaying ){
226 this.play();
227 }
228
229 return this;
230 },
231
232 promise: function( type ){
233 let _p = this._private;
234
235 let arr;
236
237 switch( type ){
238 case 'frame':
239 arr = _p.frames;
240 break;
241 default:
242 case 'complete':
243 case 'completed':
244 arr = _p.completes;
245 }
246
247 return new Promise( function( resolve, reject ){
248 arr.push( function(){
249 resolve();
250 } );
251 } );
252 }
253
254} );
255
256anifn.complete = anifn.completed;
257anifn.run = anifn.play;
258anifn.running = anifn.playing;
259
260export default Animation;