@@ -27,55 +27,23 @@ export default class Controller {
2727 this . lastTime = undefined
2828 this . guid = 0
2929 this . local = 0
30+ this . async = undefined
3031 this . update ( props )
3132 }
3233
3334 update ( props = { } ) {
3435 let { from = { } , to = { } , ...rest } = interpolateTo ( props )
3536 let isArray = is . arr ( to )
3637 let isFunction = is . fun ( to )
37- let queue = Promise . resolve ( )
38-
39- if ( isArray ) {
40- for ( let i = 0 ; i < to . length ; i ++ ) {
41- const index = i
42- const last = index === to . length - 1
43- const fresh = { ...props , to : to [ index ] }
44- if ( ! last ) fresh . onRest = undefined
45- queue = queue . then (
46- ( ) => this . local === this . guid && this . update ( interpolateTo ( fresh ) )
47- )
48- }
49- } else if ( isFunction ) {
50- let index = 0
51- let fn = to
52- queue = queue . then (
53- ( ) =>
54- new Promise ( res =>
55- fn (
56- // Next
57- ( p , last = false ) => {
58- if ( this . local === this . guid ) {
59- const fresh = { ...props , ...interpolateTo ( p ) , config }
60- if ( ! last ) fresh . onRest = undefined
61- if ( is . arr ( fresh . config ) ) fresh . config = fresh . config [ index ]
62- index ++
63- return this . update ( fresh ) . then ( ( ) => last && res ( ) )
64- }
65- } ,
66- // Cancel
67- ( ) => this . stop ( { finished : true } )
68- )
69- )
70- )
71- }
7238
73- // If "to" is either a function or an array it will be processed async, therefor "to" should be empty right now
74- // If the view relies on certain values "from" has to be present
39+ // Test again async "to"
7540 if ( isArray || isFunction ) {
7641 this . local = ++ this . guid
42+ // If "to" is either a function or an array it will be processed async, therefor "to" should be empty right now
43+ // If the view relies on certain values "from" has to be present
44+ this . async = { to, props }
7745 to = { }
78- }
46+ } else this . async = undefined
7947
8048 this . props = { ...this . props , ...rest }
8149 let {
@@ -194,32 +162,82 @@ export default class Controller {
194162 }
195163 }
196164
197- // Do not attempt to start if this is a referenced controller
198- if ( ref ) return
199- // Either return the async queue, or start a new animation
200- return isArray || isFunction ? queue : this . start ( )
165+ return this . start ( )
201166 }
202167
203- start ( ) {
204- this . startTime = now ( )
205- if ( this . isActive ) this . stop ( )
206- this . isActive = true
207- if ( this . props . onStart ) this . props . onStart ( )
208- addController ( this )
209- return new Promise ( res => ( this . resolve = res ) )
168+ // When the controller is references, it won't start on its own, even thought every update calls start and receives
169+ // a promise. The animation can then only be started by ref, which enforces it by calling start(true)
170+ start ( force = false ) {
171+ // This promise tracks the animation until onRest
172+ const promise = new Promise ( res => ( this . resolve = res ) )
173+ // Return immediately if the controller bears a reference
174+ if ( this . props . ref && force === false ) return promise
175+ // Stop all occuring animations (without resetting change-detection)
176+ this . stop ( )
177+
178+ if ( this . async ) {
179+ let { to, props } = this . async
180+ let queue = Promise . resolve ( )
181+ if ( is . arr ( to ) ) {
182+ for ( let i = 0 ; i < to . length ; i ++ ) {
183+ const index = i
184+ const last = index === to . length - 1
185+ const fresh = { ...props , to : to [ index ] }
186+ if ( is . arr ( fresh . config ) ) fresh . config = fresh . config [ index ]
187+ if ( ! last ) fresh . onRest = undefined
188+ queue = queue . then (
189+ ( ) => this . local === this . guid && this . update ( interpolateTo ( fresh ) )
190+ )
191+ }
192+ } else if ( is . fun ( to ) ) {
193+ let index = 0
194+ let fn = to
195+ queue = queue . then (
196+ ( ) =>
197+ new Promise ( res =>
198+ fn (
199+ // Next
200+ ( p , last = false ) => {
201+ if ( this . local === this . guid ) {
202+ const fresh = { ...props , ...interpolateTo ( p ) }
203+ if ( ! last ) fresh . onRest = undefined
204+ if ( is . arr ( fresh . config ) ) fresh . config = fresh . config [ index ]
205+ index ++
206+ return this . update ( fresh ) . then ( ( ) => last && res ( ) )
207+ }
208+ } ,
209+ // Cancel
210+ ( ) => this . stop ( { finished : true } )
211+ )
212+ )
213+ )
214+ }
215+ return queue . then ( this . resolve )
216+ } else {
217+ // Set start time tag
218+ this . startTime = now ( )
219+ if ( this . isActive ) this . stop ( )
220+ this . isActive = true
221+ if ( this . props . onStart ) this . props . onStart ( )
222+ addController ( this )
223+ }
224+ return promise
210225 }
211226
212227 stop ( result = { finished : false } ) {
228+ this . isActive = false
213229 removeController ( this )
214- // Reset collected changes
215- if ( result . finished )
230+
231+ if ( result . finished ) {
232+ // Reset collected changes
216233 getValues ( this . animations ) . forEach ( a => ( a . changes = undefined ) )
217- this . isActive = false
234+ // Call onRest if present
235+ if ( this . props . onRest ) this . props . onRest ( this . merged )
218236
219- if ( this . props . onRest && result . finished ) this . props . onRest ( this . merged )
220- if ( this . resolve ) {
221- this . resolve ( this . merged )
222- this . resolve = undefined
237+ if ( this . resolve ) {
238+ this . resolve ( this . merged )
239+ this . resolve = undefined
240+ }
223241 }
224242 }
225243
0 commit comments