diff options
author | Saivan <savian@me.com> | 2018-11-26 00:17:41 +1300 |
---|---|---|
committer | Saivan <savian@me.com> | 2018-11-26 00:17:41 +1300 |
commit | 617aa12304541cf1d80b2bf5567ac633958c38de (patch) | |
tree | c1082b4573625f93d18e82e6d5a0c4a40782993f /src/animation | |
parent | 599fda2f11c88b2c18d0cd0b57d4adeca20db2eb (diff) | |
download | svg.js-617aa12304541cf1d80b2bf5567ac633958c38de.tar.gz svg.js-617aa12304541cf1d80b2bf5567ac633958c38de.zip |
Reverted some of the lint rules after chatting with fuzzy
This commit reverts some of the rules we added on the linter, it changed a lot of
code again... but these won't happen too often.
Changes
=======
- Modified the linter again
Diffstat (limited to 'src/animation')
-rw-r--r-- | src/animation/Animator.js | 70 | ||||
-rw-r--r-- | src/animation/Controller.js | 240 | ||||
-rw-r--r-- | src/animation/Queue.js | 36 | ||||
-rw-r--r-- | src/animation/Runner.js | 838 | ||||
-rw-r--r-- | src/animation/Timeline.js | 194 |
5 files changed, 459 insertions, 919 deletions
diff --git a/src/animation/Animator.js b/src/animation/Animator.js index e9d5797..cac0eb9 100644 --- a/src/animation/Animator.js +++ b/src/animation/Animator.js @@ -8,106 +8,80 @@ const Animator = { timer: globals.window.performance || globals.window.Date, transforms: [], - frame ( fn ) { - + frame (fn) { // Store the node - var node = Animator.frames.push( { run: fn } ) + var node = Animator.frames.push({ run: fn }) // Request an animation frame if we don't have one - if ( Animator.nextDraw === null ) { - - Animator.nextDraw = globals.window.requestAnimationFrame( Animator._draw ) - + if (Animator.nextDraw === null) { + Animator.nextDraw = globals.window.requestAnimationFrame(Animator._draw) } // Return the node so we can remove it easily return node - }, - transform_frame ( fn, id ) { - + transform_frame (fn, id) { Animator.transforms[id] = fn - }, - timeout ( fn, delay ) { - + timeout (fn, delay) { delay = delay || 0 // Work out when the event should fire var time = Animator.timer.now() + delay // Add the timeout to the end of the queue - var node = Animator.timeouts.push( { run: fn, time: time } ) + var node = Animator.timeouts.push({ run: fn, time: time }) // Request another animation frame if we need one - if ( Animator.nextDraw === null ) { - - Animator.nextDraw = globals.window.requestAnimationFrame( Animator._draw ) - + if (Animator.nextDraw === null) { + Animator.nextDraw = globals.window.requestAnimationFrame(Animator._draw) } return node - }, - cancelFrame ( node ) { - - Animator.frames.remove( node ) - + cancelFrame (node) { + Animator.frames.remove(node) }, - clearTimeout ( node ) { - - Animator.timeouts.remove( node ) - + clearTimeout (node) { + Animator.timeouts.remove(node) }, - _draw ( now ) { - + _draw (now) { // Run all the timeouts we can run, if they are not ready yet, add them // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) var nextTimeout = null var lastTimeout = Animator.timeouts.last() - while ( ( nextTimeout = Animator.timeouts.shift() ) ) { - + while ((nextTimeout = Animator.timeouts.shift())) { // Run the timeout if its time, or push it to the end - if ( now >= nextTimeout.time ) { - + if (now >= nextTimeout.time) { nextTimeout.run() - } else { - - Animator.timeouts.push( nextTimeout ) - + Animator.timeouts.push(nextTimeout) } // If we hit the last item, we should stop shifting out more items - if ( nextTimeout === lastTimeout ) break - + if (nextTimeout === lastTimeout) break } // Run all of the animation frames var nextFrame = null var lastFrame = Animator.frames.last() - while ( ( nextFrame !== lastFrame ) && ( nextFrame = Animator.frames.shift() ) ) { - + while ((nextFrame !== lastFrame) && (nextFrame = Animator.frames.shift())) { nextFrame.run() - } - Animator.transforms.forEach( function ( el ) { - + Animator.transforms.forEach(function (el) { el() - - } ) + }) // If we have remaining timeouts or frames, draw until we don't anymore Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() - ? globals.window.requestAnimationFrame( Animator._draw ) + ? globals.window.requestAnimationFrame(Animator._draw) : null - } } diff --git a/src/animation/Controller.js b/src/animation/Controller.js index 9efe87e..6cf58cd 100644 --- a/src/animation/Controller.js +++ b/src/animation/Controller.js @@ -7,149 +7,95 @@ Base Class The base stepper class that will be ***/ -function makeSetterGetter ( k, f ) { - - return function ( v ) { - - if ( v == null ) return this[v] +function makeSetterGetter (k, f) { + return function (v) { + if (v == null) return this[v] this[k] = v - if ( f ) f.call( this ) + if (f) f.call(this) return this - } - } export let easing = { - '-': function ( pos ) { - + '-': function (pos) { return pos - }, - '<>': function ( pos ) { - - return -Math.cos( pos * Math.PI ) / 2 + 0.5 - + '<>': function (pos) { + return -Math.cos(pos * Math.PI) / 2 + 0.5 }, - '>': function ( pos ) { - - return Math.sin( pos * Math.PI / 2 ) - + '>': function (pos) { + return Math.sin(pos * Math.PI / 2) }, - '<': function ( pos ) { - - return -Math.cos( pos * Math.PI / 2 ) + 1 - + '<': function (pos) { + return -Math.cos(pos * Math.PI / 2) + 1 }, - bezier: function ( x1, y1, x2, y2 ) { - + bezier: function (x1, y1, x2, y2) { // see https://www.w3.org/TR/css-easing-1/#cubic-bezier-algo - return function ( t ) { - - if ( t < 0 ) { - - if ( x1 > 0 ) { - + return function (t) { + if (t < 0) { + if (x1 > 0) { return y1 / x1 * t - - } else if ( x2 > 0 ) { - + } else if (x2 > 0) { return y2 / x2 * t - } else { - return 0 - } - - } else if ( t > 1 ) { - - if ( x2 < 1 ) { - - return ( 1 - y2 ) / ( 1 - x2 ) * t + ( y2 - x2 ) / ( 1 - x2 ) - - } else if ( x1 < 1 ) { - - return ( 1 - y1 ) / ( 1 - x1 ) * t + ( y1 - x1 ) / ( 1 - x1 ) - + } else if (t > 1) { + if (x2 < 1) { + return (1 - y2) / (1 - x2) * t + (y2 - x2) / (1 - x2) + } else if (x1 < 1) { + return (1 - y1) / (1 - x1) * t + (y1 - x1) / (1 - x1) } else { - return 1 - } - } else { - - return 3 * t * ( 1 - t ) ** 2 * y1 + 3 * t ** 2 * ( 1 - t ) * y2 + t ** 3 - + return 3 * t * (1 - t) ** 2 * y1 + 3 * t ** 2 * (1 - t) * y2 + t ** 3 } - } - }, // see https://www.w3.org/TR/css-easing-1/#step-timing-function-algo - steps: function ( steps, stepPosition = 'end' ) { - + steps: function (steps, stepPosition = 'end') { // deal with "jump-" prefix - stepPosition = stepPosition.split( '-' ).reverse()[0] + stepPosition = stepPosition.split('-').reverse()[0] let jumps = steps - if ( stepPosition === 'none' ) { - + if (stepPosition === 'none') { --jumps - - } else if ( stepPosition === 'both' ) { - + } else if (stepPosition === 'both') { ++jumps - } // The beforeFlag is essentially useless - return ( t, beforeFlag = false ) => { - + return (t, beforeFlag = false) => { // Step is called currentStep in referenced url - let step = Math.floor( t * steps ) - const jumping = ( t * step ) % 1 === 0 - - if ( stepPosition === 'start' || stepPosition === 'both' ) { + let step = Math.floor(t * steps) + const jumping = (t * step) % 1 === 0 + if (stepPosition === 'start' || stepPosition === 'both') { ++step - } - if ( beforeFlag && jumping ) { - + if (beforeFlag && jumping) { --step - } - if ( t >= 0 && step < 0 ) { - + if (t >= 0 && step < 0) { step = 0 - } - if ( t <= 1 && step > jumps ) { - + if (t <= 1 && step > jumps) { step = jumps - } return step / jumps - } - } } export class Stepper { - done () { - return false - } - } /*** @@ -158,25 +104,17 @@ Easing Functions ***/ export class Ease extends Stepper { - - constructor ( fn ) { - + constructor (fn) { super() this.ease = easing[fn || timeline.ease] || fn - } - step ( from, to, pos ) { - - if ( typeof from !== 'number' ) { - + step (from, to, pos) { + if (typeof from !== 'number') { return pos < 1 ? from : to - } - return from + ( to - from ) * this.ease( pos ) - + return from + (to - from) * this.ease(pos) } - } /*** @@ -185,65 +123,51 @@ Controller Types ***/ export class Controller extends Stepper { - - constructor ( fn ) { - + constructor (fn) { super() this.stepper = fn - } - step ( current, target, dt, c ) { - - return this.stepper( current, target, dt, c ) - + step (current, target, dt, c) { + return this.stepper(current, target, dt, c) } - done ( c ) { - + done (c) { return c.done - } - } function recalculate () { - // Apply the default parameters - var duration = ( this._duration || 500 ) / 1000 + var duration = (this._duration || 500) / 1000 var overshoot = this._overshoot || 0 // Calculate the PID natural response var eps = 1e-10 var pi = Math.PI - var os = Math.log( overshoot / 100 + eps ) - var zeta = -os / Math.sqrt( pi * pi + os * os ) - var wn = 3.9 / ( zeta * duration ) + var os = Math.log(overshoot / 100 + eps) + var zeta = -os / Math.sqrt(pi * pi + os * os) + var wn = 3.9 / (zeta * duration) // Calculate the Spring values this.d = 2 * zeta * wn this.k = wn * wn - } export class Spring extends Controller { - - constructor ( duration, overshoot ) { - + constructor (duration, overshoot) { super() - this.duration( duration || 500 ) - .overshoot( overshoot || 0 ) - + this.duration(duration || 500) + .overshoot(overshoot || 0) } - step ( current, target, dt, c ) { - - if ( typeof current === 'string' ) return current + step (current, target, dt, c) { + if (typeof current === 'string') return current c.done = dt === Infinity - if ( dt === Infinity ) return target - if ( dt === 0 ) return current + if (dt === Infinity) return target + if (dt === 0) return current - if ( dt > 100 ) dt = 16 + if (dt > 100) dt = 16 dt /= 1000 @@ -251,7 +175,7 @@ export class Spring extends Controller { var velocity = c.velocity || 0 // Apply the control to get the new position and store it - var acceleration = -this.d * velocity - this.k * ( current - target ) + var acceleration = -this.d * velocity - this.k * (current - target) var newPosition = current + velocity * dt + acceleration * dt * dt / 2 @@ -260,66 +184,56 @@ export class Spring extends Controller { c.velocity = velocity + acceleration * dt // Figure out if we have converged, and if so, pass the value - c.done = Math.abs( target - newPosition ) + Math.abs( velocity ) < 0.002 + c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002 return c.done ? target : newPosition - } - } -extend( Spring, { - duration: makeSetterGetter( '_duration', recalculate ), - overshoot: makeSetterGetter( '_overshoot', recalculate ) -} ) +extend(Spring, { + duration: makeSetterGetter('_duration', recalculate), + overshoot: makeSetterGetter('_overshoot', recalculate) +}) export class PID extends Controller { - - constructor ( p, i, d, windup ) { - + constructor (p, i, d, windup) { super() p = p == null ? 0.1 : p i = i == null ? 0.01 : i d = d == null ? 0 : d windup = windup == null ? 1000 : windup - this.p( p ).i( i ).d( d ).windup( windup ) - + this.p(p).i(i).d(d).windup(windup) } - step ( current, target, dt, c ) { - - if ( typeof current === 'string' ) return current + step (current, target, dt, c) { + if (typeof current === 'string') return current c.done = dt === Infinity - if ( dt === Infinity ) return target - if ( dt === 0 ) return current + if (dt === Infinity) return target + if (dt === 0) return current var p = target - current - var i = ( c.integral || 0 ) + p * dt - var d = ( p - ( c.error || 0 ) ) / dt + var i = (c.integral || 0) + p * dt + var d = (p - (c.error || 0)) / dt var windup = this.windup // antiwindup - if ( windup !== false ) { - - i = Math.max( -windup, Math.min( i, windup ) ) - + if (windup !== false) { + i = Math.max(-windup, Math.min(i, windup)) } c.error = p c.integral = i - c.done = Math.abs( p ) < 0.001 - - return c.done ? target : current + ( this.P * p + this.I * i + this.D * d ) + c.done = Math.abs(p) < 0.001 + return c.done ? target : current + (this.P * p + this.I * i + this.D * d) } - } -extend( PID, { - windup: makeSetterGetter( 'windup' ), - p: makeSetterGetter( 'P' ), - i: makeSetterGetter( 'I' ), - d: makeSetterGetter( 'D' ) -} ) +extend(PID, { + windup: makeSetterGetter('windup'), + p: makeSetterGetter('P'), + i: makeSetterGetter('I'), + d: makeSetterGetter('D') +}) diff --git a/src/animation/Queue.js b/src/animation/Queue.js index b4e2722..14b92b4 100644 --- a/src/animation/Queue.js +++ b/src/animation/Queue.js @@ -1,77 +1,59 @@ export default class Queue { - constructor () { - this._first = null this._last = null - } - push ( value ) { - + push (value) { // An item stores an id and the provided value var item = value.next ? value : { value: value, next: null, prev: null } // Deal with the queue being empty or populated - if ( this._last ) { - + if (this._last) { item.prev = this._last this._last.next = item this._last = item - } else { - this._last = item this._first = item - } // Update the length and return the current item return item - } shift () { - // Check if we have a value var remove = this._first - if ( !remove ) return null + if (!remove) return null // If we do, remove it and relink things this._first = remove.next - if ( this._first ) this._first.prev = null + if (this._first) this._first.prev = null this._last = this._first ? this._last : null return remove.value - } // Shows us the first item in the list first () { - return this._first && this._first.value - } // Shows us the last item in the list last () { - return this._last && this._last.value - } // Removes the item that was returned from the push - remove ( item ) { - + remove (item) { // Relink the previous item - if ( item.prev ) item.prev.next = item.next - if ( item.next ) item.next.prev = item.prev - if ( item === this._last ) this._last = item.prev - if ( item === this._first ) this._first = item.next + if (item.prev) item.prev.next = item.next + if (item.next) item.next.prev = item.prev + if (item === this._last) this._last = item.prev + if (item === this._first) this._first = item.next // Invalidate item item.prev = null item.next = null - } - } diff --git a/src/animation/Runner.js b/src/animation/Runner.js index d2c7bdf..7e04c21 100644 --- a/src/animation/Runner.js +++ b/src/animation/Runner.js @@ -15,9 +15,7 @@ import SVGNumber from '../types/SVGNumber.js' import Timeline from './Timeline.js' export default class Runner extends EventTarget { - - constructor ( options ) { - + constructor (options) { super() // Store a unique id on the runner, so that we can identify it later @@ -30,7 +28,7 @@ export default class Runner extends EventTarget { // Ensure that we get a controller options = typeof options === 'function' - ? new Controller( options ) + ? new Controller(options) : options // Declare all of the variables @@ -63,7 +61,6 @@ export default class Runner extends EventTarget { this._swing = false this._wait = 0 this._times = 1 - } /* @@ -73,75 +70,58 @@ export default class Runner extends EventTarget { help us make new runners from the current runner */ - element ( element ) { - - if ( element == null ) return this._element + element (element) { + if (element == null) return this._element this._element = element element._prepareRunner() return this - } - timeline ( timeline ) { - + timeline (timeline) { // check explicitly for undefined so we can set the timeline to null - if ( typeof timeline === 'undefined' ) return this._timeline + if (typeof timeline === 'undefined') return this._timeline this._timeline = timeline return this - } - animate ( duration, delay, when ) { - - var o = Runner.sanitise( duration, delay, when ) - var runner = new Runner( o.duration ) - if ( this._timeline ) runner.timeline( this._timeline ) - if ( this._element ) runner.element( this._element ) - return runner.loop( o ).schedule( delay, when ) - + animate (duration, delay, when) { + var o = Runner.sanitise(duration, delay, when) + var runner = new Runner(o.duration) + if (this._timeline) runner.timeline(this._timeline) + if (this._element) runner.element(this._element) + return runner.loop(o).schedule(delay, when) } - schedule ( timeline, delay, when ) { - + schedule (timeline, delay, when) { // The user doesn't need to pass a timeline if we already have one - if ( !( timeline instanceof Timeline ) ) { - + if (!(timeline instanceof Timeline)) { when = delay delay = timeline timeline = this.timeline() - } // If there is no timeline, yell at the user... - if ( !timeline ) { - - throw Error( 'Runner cannot be scheduled without timeline' ) - + if (!timeline) { + throw Error('Runner cannot be scheduled without timeline') } // Schedule the runner on the timeline provided - timeline.schedule( this, delay, when ) + timeline.schedule(this, delay, when) return this - } unschedule () { - var timeline = this.timeline() - timeline && timeline.unschedule( this ) + timeline && timeline.unschedule(this) return this - } - loop ( times, swing, wait ) { - + loop (times, swing, wait) { // Deal with the user passing in an object - if ( typeof times === 'object' ) { - + if (typeof times === 'object') { swing = times.swing wait = times.wait times = times.times - } // Sanitise the values and store them @@ -149,13 +129,10 @@ export default class Runner extends EventTarget { this._swing = swing || false this._wait = wait || 0 return this - } - delay ( delay ) { - - return this.animate( 0, delay ) - + delay (delay) { + return this.animate(0, delay) } /* @@ -164,32 +141,26 @@ export default class Runner extends EventTarget { These methods allow us to attach basic functions to the runner directly */ - queue ( initFn, runFn, retargetFn, isTransform ) { - - this._queue.push( { + queue (initFn, runFn, retargetFn, isTransform) { + this._queue.push({ initialiser: initFn || noop, runner: runFn || noop, retarget: retargetFn, isTransform: isTransform, initialised: false, finished: false - } ) + }) var timeline = this.timeline() timeline && this.timeline()._continue() return this - } - during ( fn ) { - - return this.queue( null, fn ) - + during (fn) { + return this.queue(null, fn) } - after ( fn ) { - - return this.on( 'finish', fn ) - + after (fn) { + return this.on('finish', fn) } /* @@ -198,45 +169,34 @@ export default class Runner extends EventTarget { Control how the animation plays */ - time ( time ) { - - if ( time == null ) { - + time (time) { + if (time == null) { return this._time - } let dt = time - this._time - this.step( dt ) + this.step(dt) return this - } duration () { - - return this._times * ( this._wait + this._duration ) - this._wait - + return this._times * (this._wait + this._duration) - this._wait } - loops ( p ) { - + loops (p) { var loopDuration = this._duration + this._wait - if ( p == null ) { - - var loopsDone = Math.floor( this._time / loopDuration ) - var relativeTime = ( this._time - loopsDone * loopDuration ) + if (p == null) { + var loopsDone = Math.floor(this._time / loopDuration) + var relativeTime = (this._time - loopsDone * loopDuration) var position = relativeTime / this._duration - return Math.min( loopsDone + position, this._times ) - + return Math.min(loopsDone + position, this._times) } - var whole = Math.floor( p ) + var whole = Math.floor(p) var partial = p % 1 var time = loopDuration * whole + this._duration * partial - return this.time( time ) - + return this.time(time) } - position ( p ) { - + position (p) { // Get all of the variables we need var x = this._time var d = this._duration @@ -246,8 +206,7 @@ export default class Runner extends EventTarget { var r = this._reverse var position - if ( p == null ) { - + if (p == null) { /* This function converts a time to a position in the range [0, 1] The full explanation can be found in this desmos demonstration @@ -256,49 +215,40 @@ export default class Runner extends EventTarget { */ // Figure out the value without thinking about the start or end time - const f = function ( x ) { - - var swinging = s * Math.floor( x % ( 2 * ( w + d ) ) / ( w + d ) ) - var backwards = ( swinging && !r ) || ( !swinging && r ) - var uncliped = Math.pow( -1, backwards ) * ( x % ( w + d ) ) / d + backwards - var clipped = Math.max( Math.min( uncliped, 1 ), 0 ) + const f = function (x) { + var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)) + var backwards = (swinging && !r) || (!swinging && r) + var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards + var clipped = Math.max(Math.min(uncliped, 1), 0) return clipped - } // Figure out the value by incorporating the start time - var endTime = t * ( w + d ) - w - position = x <= 0 ? Math.round( f( 1e-5 ) ) - : x < endTime ? f( x ) - : Math.round( f( endTime - 1e-5 ) ) + var endTime = t * (w + d) - w + position = x <= 0 ? Math.round(f(1e-5)) + : x < endTime ? f(x) + : Math.round(f(endTime - 1e-5)) return position - } // Work out the loops done and add the position to the loops done - var loopsDone = Math.floor( this.loops() ) - var swingForward = s && ( loopsDone % 2 === 0 ) - var forwards = ( swingForward && !r ) || ( r && swingForward ) - position = loopsDone + ( forwards ? p : 1 - p ) - return this.loops( position ) - + var loopsDone = Math.floor(this.loops()) + var swingForward = s && (loopsDone % 2 === 0) + var forwards = (swingForward && !r) || (r && swingForward) + position = loopsDone + (forwards ? p : 1 - p) + return this.loops(position) } - progress ( p ) { - - if ( p == null ) { - - return Math.min( 1, this._time / this.duration() ) - + progress (p) { + if (p == null) { + return Math.min(1, this._time / this.duration()) } - return this.time( p * this.duration() ) - + return this.time(p * this.duration()) } - step ( dt ) { - + step (dt) { // If we are inactive, this stepper just gets skipped - if ( !this.enabled ) return this + if (!this.enabled) return this // Update the time and get the new position dt = dt == null ? 16 : dt @@ -314,10 +264,8 @@ export default class Runner extends EventTarget { var justStarted = this._lastTime < 0 && this._time > 0 var justFinished = this._lastTime < this._time && this.time > duration this._lastTime = this._time - if ( justStarted ) { - - this.fire( 'start', this ) - + if (justStarted) { + this.fire('start', this) } // Work out if the runner is finished set the done flag here so animations @@ -327,54 +275,41 @@ export default class Runner extends EventTarget { this.done = !declarative && !justFinished && this._time >= duration // Call initialise and the run function - if ( running || declarative ) { - - this._initialise( running ) + if (running || declarative) { + this._initialise(running) // clear the transforms on this runner so they dont get added again and again this.transforms = new Matrix() - var converged = this._run( declarative ? dt : position ) - this.fire( 'step', this ) - + var converged = this._run(declarative ? dt : position) + this.fire('step', this) } // correct the done flag here // declaritive animations itself know when they converged - this.done = this.done || ( converged && declarative ) - if ( this.done ) { - - this.fire( 'finish', this ) - + this.done = this.done || (converged && declarative) + if (this.done) { + this.fire('finish', this) } return this - } finish () { - - return this.step( Infinity ) - + return this.step(Infinity) } - reverse ( reverse ) { - + reverse (reverse) { this._reverse = reverse == null ? !this._reverse : reverse return this - } - ease ( fn ) { - - this._stepper = new Ease( fn ) + ease (fn) { + this._stepper = new Ease(fn) return this - } - active ( enabled ) { - - if ( enabled == null ) return this.enabled + active (enabled) { + if (enabled == null) return this.enabled this.enabled = enabled return this - } /* @@ -384,135 +319,102 @@ export default class Runner extends EventTarget { */ // Save a morpher to the morpher list so that we can retarget it later - _rememberMorpher ( method, morpher ) { - + _rememberMorpher (method, morpher) { this._history[method] = { morpher: morpher, caller: this._queue[this._queue.length - 1] } - } // Try to set the target for a morpher if the morpher exists, otherwise // do nothing and return false - _tryRetarget ( method, target ) { - - if ( this._history[method] ) { - + _tryRetarget (method, target) { + if (this._history[method]) { // if the last method wasnt even initialised, throw it away - if ( !this._history[method].caller.initialised ) { - - let index = this._queue.indexOf( this._history[method].caller ) - this._queue.splice( index, 1 ) + if (!this._history[method].caller.initialised) { + let index = this._queue.indexOf(this._history[method].caller) + this._queue.splice(index, 1) return false - } // for the case of transformations, we use the special retarget function // which has access to the outer scope - if ( this._history[method].caller.retarget ) { - - this._history[method].caller.retarget( target ) + if (this._history[method].caller.retarget) { + this._history[method].caller.retarget(target) // for everything else a simple morpher change is sufficient - } else { - - this._history[method].morpher.to( target ) - + this._history[method].morpher.to(target) } this._history[method].caller.finished = false var timeline = this.timeline() timeline && timeline._continue() return true - } return false - } // Run each initialise function in the runner if required - _initialise ( running ) { - + _initialise (running) { // If we aren't running, we shouldn't initialise when not declarative - if ( !running && !this._isDeclarative ) return + if (!running && !this._isDeclarative) return // Loop through all of the initialisers - for ( var i = 0, len = this._queue.length; i < len; ++i ) { - + for (var i = 0, len = this._queue.length; i < len; ++i) { // Get the current initialiser var current = this._queue[i] // Determine whether we need to initialise - var needsIt = this._isDeclarative || ( !current.initialised && running ) + var needsIt = this._isDeclarative || (!current.initialised && running) running = !current.finished // Call the initialiser if we need to - if ( needsIt && running ) { - - current.initialiser.call( this ) + if (needsIt && running) { + current.initialiser.call(this) current.initialised = true - } - } - } // Run each run function for the position or dt given - _run ( positionOrDt ) { - + _run (positionOrDt) { // Run all of the _queue directly var allfinished = true - for ( var i = 0, len = this._queue.length; i < len; ++i ) { - + for (var i = 0, len = this._queue.length; i < len; ++i) { // Get the current function to run var current = this._queue[i] // Run the function if its not finished, we keep track of the finished // flag for the sake of declarative _queue - var converged = current.runner.call( this, positionOrDt ) - current.finished = current.finished || ( converged === true ) + var converged = current.runner.call(this, positionOrDt) + current.finished = current.finished || (converged === true) allfinished = allfinished && current.finished - } // We report when all of the constructors are finished return allfinished - } - addTransform ( transform, index ) { - - this.transforms.lmultiplyO( transform ) + addTransform (transform, index) { + this.transforms.lmultiplyO(transform) return this - } clearTransform () { - this.transforms = new Matrix() return this - } // TODO: Keep track of all transformations so that deletion is faster clearTransformsFromQueue () { - - if ( !this.done ) { - - this._queue = this._queue.filter( ( item ) => { - + if (!this.done) { + this._queue = this._queue.filter((item) => { return !item.isTransform - - } ) - + }) } - } - static sanitise ( duration, delay, when ) { - + static sanitise (duration, delay, when) { // Initialise the default parameters var times = 1 var swing = false @@ -522,15 +424,13 @@ export default class Runner extends EventTarget { when = when || 'last' // If we have an object, unpack the values - if ( typeof duration === 'object' && !( duration instanceof Stepper ) ) { - + if (typeof duration === 'object' && !(duration instanceof Stepper)) { delay = duration.delay || delay when = duration.when || when swing = duration.swing || swing times = duration.times || times wait = duration.wait || wait duration = duration.duration || timeline.duration - } return { @@ -541,285 +441,215 @@ export default class Runner extends EventTarget { wait: wait, when: when } - } - } Runner.id = 0 class FakeRunner { - - constructor ( transforms = new Matrix(), id = -1, done = true ) { - + constructor (transforms = new Matrix(), id = -1, done = true) { this.transforms = transforms this.id = id this.done = done - } clearTransformsFromQueue () { } - } -extend( [ Runner, FakeRunner ], { - mergeWith ( runner ) { - +extend([ Runner, FakeRunner ], { + mergeWith (runner) { return new FakeRunner( - runner.transforms.lmultiply( this.transforms ), + runner.transforms.lmultiply(this.transforms), runner.id ) - } -} ) +}) // FakeRunner.emptyRunner = new FakeRunner() -const lmultiply = ( last, curr ) => last.lmultiplyO( curr ) -const getRunnerTransform = ( runner ) => runner.transforms +const lmultiply = (last, curr) => last.lmultiplyO(curr) +const getRunnerTransform = (runner) => runner.transforms function mergeTransforms () { - // Find the matrix to apply to the element and apply it let runners = this._transformationRunners.runners let netTransform = runners - .map( getRunnerTransform ) - .reduce( lmultiply, new Matrix() ) + .map(getRunnerTransform) + .reduce(lmultiply, new Matrix()) - this.transform( netTransform ) + this.transform(netTransform) this._transformationRunners.merge() - if ( this._transformationRunners.length() === 1 ) { - + if (this._transformationRunners.length() === 1) { this._frameId = null - } - } class RunnerArray { - constructor () { - this.runners = [] this.ids = [] - } - add ( runner ) { - - if ( this.runners.includes( runner ) ) return + add (runner) { + if (this.runners.includes(runner)) return let id = runner.id + 1 - let leftSibling = this.ids.reduce( ( last, curr ) => { - - if ( curr > last && curr < id ) return curr + let leftSibling = this.ids.reduce((last, curr) => { + if (curr > last && curr < id) return curr return last + }, 0) - }, 0 ) + let index = this.ids.indexOf(leftSibling) + 1 - let index = this.ids.indexOf( leftSibling ) + 1 - - this.ids.splice( index, 0, id ) - this.runners.splice( index, 0, runner ) + this.ids.splice(index, 0, id) + this.runners.splice(index, 0, runner) return this - } - getByID ( id ) { - - return this.runners[this.ids.indexOf( id + 1 )] - + getByID (id) { + return this.runners[this.ids.indexOf(id + 1)] } - remove ( id ) { - - let index = this.ids.indexOf( id + 1 ) - this.ids.splice( index, 1 ) - this.runners.splice( index, 1 ) + remove (id) { + let index = this.ids.indexOf(id + 1) + this.ids.splice(index, 1) + this.runners.splice(index, 1) return this - } merge () { - let lastRunner = null - this.runners.forEach( ( runner, i ) => { - - if ( lastRunner && runner.done && lastRunner.done ) { - - this.remove( runner.id ) - this.edit( lastRunner.id, runner.mergeWith( lastRunner ) ) - + this.runners.forEach((runner, i) => { + if (lastRunner && runner.done && lastRunner.done) { + this.remove(runner.id) + this.edit(lastRunner.id, runner.mergeWith(lastRunner)) } lastRunner = runner - - } ) + }) return this - } - edit ( id, newRunner ) { - - let index = this.ids.indexOf( id + 1 ) - this.ids.splice( index, 1, id ) - this.runners.splice( index, 1, newRunner ) + edit (id, newRunner) { + let index = this.ids.indexOf(id + 1) + this.ids.splice(index, 1, id) + this.runners.splice(index, 1, newRunner) return this - } length () { - return this.ids.length - } - clearBefore ( id ) { - - let deleteCnt = this.ids.indexOf( id + 1 ) || 1 - this.ids.splice( 0, deleteCnt, 0 ) - this.runners.splice( 0, deleteCnt, new FakeRunner() ) - .forEach( ( r ) => r.clearTransformsFromQueue() ) + clearBefore (id) { + let deleteCnt = this.ids.indexOf(id + 1) || 1 + this.ids.splice(0, deleteCnt, 0) + this.runners.splice(0, deleteCnt, new FakeRunner()) + .forEach((r) => r.clearTransformsFromQueue()) return this - } - } let frameId = 0 -registerMethods( { +registerMethods({ Element: { - animate ( duration, delay, when ) { - - var o = Runner.sanitise( duration, delay, when ) + animate (duration, delay, when) { + var o = Runner.sanitise(duration, delay, when) var timeline = this.timeline() - return new Runner( o.duration ) - .loop( o ) - .element( this ) - .timeline( timeline ) - .schedule( delay, when ) - + return new Runner(o.duration) + .loop(o) + .element(this) + .timeline(timeline) + .schedule(delay, when) }, - delay ( by, when ) { - - return this.animate( 0, by, when ) - + delay (by, when) { + return this.animate(0, by, when) }, // this function searches for all runners on the element and deletes the ones // which run before the current one. This is because absolute transformations // overwfrite anything anyway so there is no need to waste time computing // other runners - _clearTransformRunnersBefore ( currentRunner ) { - - this._transformationRunners.clearBefore( currentRunner.id ) - + _clearTransformRunnersBefore (currentRunner) { + this._transformationRunners.clearBefore(currentRunner.id) }, - _currentTransform ( current ) { - + _currentTransform (current) { return this._transformationRunners.runners // we need the equal sign here to make sure, that also transformations // on the same runner which execute before the current transformation are // taken into account - .filter( ( runner ) => runner.id <= current.id ) - .map( getRunnerTransform ) - .reduce( lmultiply, new Matrix() ) - + .filter((runner) => runner.id <= current.id) + .map(getRunnerTransform) + .reduce(lmultiply, new Matrix()) }, - addRunner ( runner ) { - - this._transformationRunners.add( runner ) + addRunner (runner) { + this._transformationRunners.add(runner) Animator.transform_frame( - mergeTransforms.bind( this ), this._frameId + mergeTransforms.bind(this), this._frameId ) - }, _prepareRunner () { - - if ( this._frameId == null ) { - + if (this._frameId == null) { this._transformationRunners = new RunnerArray() - .add( new FakeRunner( new Matrix( this ) ) ) + .add(new FakeRunner(new Matrix(this))) this._frameId = frameId++ - } - } } -} ) - -extend( Runner, { - attr ( a, v ) { - - return this.styleAttr( 'attr', a, v ) +}) +extend(Runner, { + attr (a, v) { + return this.styleAttr('attr', a, v) }, // Add animatable styles - css ( s, v ) { - - return this.styleAttr( 'css', s, v ) - + css (s, v) { + return this.styleAttr('css', s, v) }, - styleAttr ( type, name, val ) { - + styleAttr (type, name, val) { // apply attributes individually - if ( typeof name === 'object' ) { - - for ( var key in val ) { - - this.styleAttr( type, key, val[key] ) - + if (typeof name === 'object') { + for (var key in val) { + this.styleAttr(type, key, val[key]) } - } - var morpher = new Morphable( this._stepper ).to( val ) - - this.queue( function () { - - morpher = morpher.from( this.element()[type]( name ) ) - - }, function ( pos ) { + var morpher = new Morphable(this._stepper).to(val) - this.element()[type]( name, morpher.at( pos ) ) + this.queue(function () { + morpher = morpher.from(this.element()[type](name)) + }, function (pos) { + this.element()[type](name, morpher.at(pos)) return morpher.done() - - } ) + }) return this - }, - zoom ( level, point ) { - - var morpher = new Morphable( this._stepper ).to( new SVGNumber( level ) ) - - this.queue( function () { + zoom (level, point) { + var morpher = new Morphable(this._stepper).to(new SVGNumber(level)) - morpher = morpher.from( this.zoom() ) - - }, function ( pos ) { - - this.element().zoom( morpher.at( pos ), point ) + this.queue(function () { + morpher = morpher.from(this.zoom()) + }, function (pos) { + this.element().zoom(morpher.at(pos), point) return morpher.done() - - } ) + }) return this - }, /** @@ -839,25 +669,22 @@ extend( Runner, { // - Note F(1) = T // 4. Now you get the delta matrix as a result: D = F * inv(M) - transform ( transforms, relative, affine ) { - + transform (transforms, relative, affine) { // If we have a declarative function, we should retarget it if possible relative = transforms.relative || relative - if ( this._isDeclarative && !relative && this._tryRetarget( 'transform', transforms ) ) { - + if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { return this - } // Parse the parameters - var isMatrix = Matrix.isMatrixLike( transforms ) + var isMatrix = Matrix.isMatrixLike(transforms) affine = transforms.affine != null ? transforms.affine - : ( affine != null ? affine : !isMatrix ) + : (affine != null ? affine : !isMatrix) // Create a morepher and set its type - const morpher = new Morphable( this._stepper ) - .type( affine ? TransformBag : Matrix ) + const morpher = new Morphable(this._stepper) + .type(affine ? TransformBag : Matrix) let origin let element @@ -866,42 +693,36 @@ extend( Runner, { let startTransform function setup () { - // make sure element and origin is defined element = element || this.element() - origin = origin || getOrigin( transforms, element ) + origin = origin || getOrigin(transforms, element) - startTransform = new Matrix( relative ? undefined : element ) + startTransform = new Matrix(relative ? undefined : element) // add the runner to the element so it can merge transformations - element.addRunner( this ) + element.addRunner(this) // Deactivate all transforms that have run so far if we are absolute - if ( !relative ) { - - element._clearTransformRunnersBefore( this ) - + if (!relative) { + element._clearTransformRunnersBefore(this) } - } - function run ( pos ) { - + function run (pos) { // clear all other transforms before this in case something is saved // on this runner. We are absolute. We dont need these! - if ( !relative ) this.clearTransform() + if (!relative) this.clearTransform() - let { x, y } = new Point( origin ).transform( element._currentTransform( this ) ) + let { x, y } = new Point(origin).transform(element._currentTransform(this)) - let target = new Matrix( { ...transforms, origin: [ x, y ] } ) + let target = new Matrix({ ...transforms, origin: [ x, y ] }) let start = this._isDeclarative && current ? current : startTransform - if ( affine ) { - - target = target.decompose( x, y ) - start = start.decompose( x, y ) + if (affine) { + target = target.decompose(x, y) + start = start.decompose(x, y) // Get the current and target angle as it was set const rTarget = target.rotate @@ -909,285 +730,212 @@ extend( Runner, { // Figure out the shortest path to rotate directly const possibilities = [ rTarget - 360, rTarget, rTarget + 360 ] - const distances = possibilities.map( a => Math.abs( a - rCurrent ) ) - const shortest = Math.min( ...distances ) - const index = distances.indexOf( shortest ) + const distances = possibilities.map(a => Math.abs(a - rCurrent)) + const shortest = Math.min(...distances) + const index = distances.indexOf(shortest) target.rotate = possibilities[index] - } - if ( relative ) { - + if (relative) { // we have to be careful here not to overwrite the rotation // with the rotate method of Matrix - if ( !isMatrix ) { - + if (!isMatrix) { target.rotate = transforms.rotate || 0 - } - if ( this._isDeclarative && currentAngle ) { - + if (this._isDeclarative && currentAngle) { start.rotate = currentAngle - } - } - morpher.from( start ) - morpher.to( target ) + morpher.from(start) + morpher.to(target) - let affineParameters = morpher.at( pos ) + let affineParameters = morpher.at(pos) currentAngle = affineParameters.rotate - current = new Matrix( affineParameters ) + current = new Matrix(affineParameters) - this.addTransform( current ) + this.addTransform(current) return morpher.done() - } - function retarget ( newTransforms ) { - + function retarget (newTransforms) { // only get a new origin if it changed since the last call if ( - ( newTransforms.origin || 'center' ).toString() - !== ( transforms.origin || 'center' ).toString() + (newTransforms.origin || 'center').toString() + !== (transforms.origin || 'center').toString() ) { - - origin = getOrigin( transforms, element ) - + origin = getOrigin(transforms, element) } // overwrite the old transformations with the new ones transforms = { ...newTransforms, origin } - } - this.queue( setup, run, retarget, true ) - this._isDeclarative && this._rememberMorpher( 'transform', morpher ) + this.queue(setup, run, retarget, true) + this._isDeclarative && this._rememberMorpher('transform', morpher) return this - }, // Animatable x-axis - x ( x, relative ) { - - return this._queueNumber( 'x', x ) - + x (x, relative) { + return this._queueNumber('x', x) }, // Animatable y-axis - y ( y ) { - - return this._queueNumber( 'y', y ) - + y (y) { + return this._queueNumber('y', y) }, - dx ( x ) { - - return this._queueNumberDelta( 'x', x ) - + dx (x) { + return this._queueNumberDelta('x', x) }, - dy ( y ) { - - return this._queueNumberDelta( 'y', y ) - + dy (y) { + return this._queueNumberDelta('y', y) }, - _queueNumberDelta ( method, to ) { - - to = new SVGNumber( to ) + _queueNumberDelta (method, to) { + to = new SVGNumber(to) // Try to change the target if we have this method already registerd - if ( this._tryRetarget( method, to ) ) return this + if (this._tryRetarget(method, to)) return this // Make a morpher and queue the animation - var morpher = new Morphable( this._stepper ).to( to ) + var morpher = new Morphable(this._stepper).to(to) var from = null - this.queue( function () { - + this.queue(function () { from = this.element()[method]() - morpher.from( from ) - morpher.to( from + to ) - - }, function ( pos ) { - - this.element()[method]( morpher.at( pos ) ) + morpher.from(from) + morpher.to(from + to) + }, function (pos) { + this.element()[method](morpher.at(pos)) return morpher.done() - - }, function ( newTo ) { - - morpher.to( from + new SVGNumber( newTo ) ) - - } ) + }, function (newTo) { + morpher.to(from + new SVGNumber(newTo)) + }) // Register the morpher so that if it is changed again, we can retarget it - this._rememberMorpher( method, morpher ) + this._rememberMorpher(method, morpher) return this - }, - _queueObject ( method, to ) { - + _queueObject (method, to) { // Try to change the target if we have this method already registerd - if ( this._tryRetarget( method, to ) ) return this + if (this._tryRetarget(method, to)) return this // Make a morpher and queue the animation - var morpher = new Morphable( this._stepper ).to( to ) - this.queue( function () { - - morpher.from( this.element()[method]() ) - - }, function ( pos ) { - - this.element()[method]( morpher.at( pos ) ) + var morpher = new Morphable(this._stepper).to(to) + this.queue(function () { + morpher.from(this.element()[method]()) + }, function (pos) { + this.element()[method](morpher.at(pos)) return morpher.done() - - } ) + }) // Register the morpher so that if it is changed again, we can retarget it - this._rememberMorpher( method, morpher ) + this._rememberMorpher(method, morpher) return this - }, - _queueNumber ( method, value ) { - - return this._queueObject( method, new SVGNumber( value ) ) - + _queueNumber (method, value) { + return this._queueObject(method, new SVGNumber(value)) }, // Animatable center x-axis - cx ( x ) { - - return this._queueNumber( 'cx', x ) - + cx (x) { + return this._queueNumber('cx', x) }, // Animatable center y-axis - cy ( y ) { - - return this._queueNumber( 'cy', y ) - + cy (y) { + return this._queueNumber('cy', y) }, // Add animatable move - move ( x, y ) { - - return this.x( x ).y( y ) - + move (x, y) { + return this.x(x).y(y) }, // Add animatable center - center ( x, y ) { - - return this.cx( x ).cy( y ) - + center (x, y) { + return this.cx(x).cy(y) }, // Add animatable size - size ( width, height ) { - + size (width, height) { // animate bbox based size for all other elements var box - if ( !width || !height ) { - + if (!width || !height) { box = this._element.bbox() - } - if ( !width ) { - + if (!width) { width = box.width / box.height * height - } - if ( !height ) { - + if (!height) { height = box.height / box.width * width - } return this - .width( width ) - .height( height ) - + .width(width) + .height(height) }, // Add animatable width - width ( width ) { - - return this._queueNumber( 'width', width ) - + width (width) { + return this._queueNumber('width', width) }, // Add animatable height - height ( height ) { - - return this._queueNumber( 'height', height ) - + height (height) { + return this._queueNumber('height', height) }, // Add animatable plot - plot ( a, b, c, d ) { - + plot (a, b, c, d) { // Lines can be plotted with 4 arguments - if ( arguments.length === 4 ) { - - return this.plot( [ a, b, c, d ] ) - + if (arguments.length === 4) { + return this.plot([ a, b, c, d ]) } - var morpher = this._element.MorphArray().to( a ) - - this.queue( function () { - - morpher.from( this._element.array() ) + var morpher = this._element.MorphArray().to(a) - }, function ( pos ) { - - this._element.plot( morpher.at( pos ) ) - - } ) + this.queue(function () { + morpher.from(this._element.array()) + }, function (pos) { + this._element.plot(morpher.at(pos)) + }) return this - }, // Add leading method - leading ( value ) { - - return this._queueNumber( 'leading', value ) - + leading (value) { + return this._queueNumber('leading', value) }, // Add animatable viewbox - viewbox ( x, y, width, height ) { - - return this._queueObject( 'viewbox', new Box( x, y, width, height ) ) - + viewbox (x, y, width, height) { + return this._queueObject('viewbox', new Box(x, y, width, height)) }, - update ( o ) { - - if ( typeof o !== 'object' ) { - - return this.update( { + update (o) { + if (typeof o !== 'object') { + return this.update({ offset: arguments[0], color: arguments[1], opacity: arguments[2] - } ) - + }) } - if ( o.opacity != null ) this.attr( 'stop-opacity', o.opacity ) - if ( o.color != null ) this.attr( 'stop-color', o.color ) - if ( o.offset != null ) this.attr( 'offset', o.offset ) + if (o.opacity != null) this.attr('stop-opacity', o.opacity) + if (o.color != null) this.attr('stop-color', o.color) + if (o.offset != null) this.attr('offset', o.offset) return this - } -} ) +}) -extend( Runner, { rx, ry, from, to } ) +extend(Runner, { rx, ry, from, to }) diff --git a/src/animation/Timeline.js b/src/animation/Timeline.js index 2fa281c..6abcb80 100644 --- a/src/animation/Timeline.js +++ b/src/animation/Timeline.js @@ -3,27 +3,21 @@ import { registerMethods } from '../utils/methods.js' import Animator from './Animator.js' import EventTarget from '../types/EventTarget.js' -var makeSchedule = function ( runnerInfo ) { - +var makeSchedule = function (runnerInfo) { var start = runnerInfo.start var duration = runnerInfo.runner.duration() var end = start + duration return { start: start, duration: duration, end: end, runner: runnerInfo.runner } - } export default class Timeline extends EventTarget { - // Construct a new timeline on the given element constructor () { - super() this._timeSource = function () { - let w = globals.window - return ( w.performance || w.Date ).now() - + return (w.performance || w.Date).now() } // Store the timing variables @@ -42,7 +36,6 @@ export default class Timeline extends EventTarget { this._time = 0 this._lastSourceTime = 0 this._lastStepTime = 0 - } /** @@ -50,28 +43,19 @@ export default class Timeline extends EventTarget { */ // schedules a runner on the timeline - schedule ( runner, delay, when ) { - + schedule (runner, delay, when) { // FIXME: how to sort? maybe by runner id? - if ( runner == null ) { - - return this._runners.map( makeSchedule ).sort( function ( a, b ) { - - return ( a.start - b.start ) || ( a.duration - b.duration ) - - } ) - + if (runner == null) { + return this._runners.map(makeSchedule).sort(function (a, b) { + return (a.start - b.start) || (a.duration - b.duration) + }) } - if ( !this.active() ) { - + if (!this.active()) { this._step() - if ( when == null ) { - + if (when == null) { when = 'now' - } - } // The start time for the next animation can either be given explicitly, @@ -81,40 +65,28 @@ export default class Timeline extends EventTarget { delay = delay || 0 // Work out when to start the animation - if ( when == null || when === 'last' || when === 'after' ) { - + if (when == null || when === 'last' || when === 'after') { // Take the last time and increment absoluteStartTime = this._startTime - - } else if ( when === 'absolute' || when === 'start' ) { - + } else if (when === 'absolute' || when === 'start') { absoluteStartTime = delay delay = 0 - - } else if ( when === 'now' ) { - + } else if (when === 'now') { absoluteStartTime = this._time - - } else if ( when === 'relative' ) { - + } else if (when === 'relative') { let runnerInfo = this._runners[runner.id] - if ( runnerInfo ) { - + if (runnerInfo) { absoluteStartTime = runnerInfo.start + delay delay = 0 - } - } else { - - throw new Error( 'Invalid value for the "when" parameter' ) - + throw new Error('Invalid value for the "when" parameter') } // Manage runner runner.unschedule() - runner.timeline( this ) - runner.time( -delay ) + runner.timeline(this) + runner.time(-delay) // Save startTime for next runner this._startTime = absoluteStartTime + runner.duration() + delay @@ -127,115 +99,91 @@ export default class Timeline extends EventTarget { } // Save order and continue - this._order.push( runner.id ) + this._order.push(runner.id) this._continue() return this - } // Remove the runner from this timeline - unschedule ( runner ) { - - var index = this._order.indexOf( runner.id ) - if ( index < 0 ) return this + unschedule (runner) { + var index = this._order.indexOf(runner.id) + if (index < 0) return this delete this._runners[runner.id] - this._order.splice( index, 1 ) - runner.timeline( null ) + this._order.splice(index, 1) + runner.timeline(null) return this - } play () { - // Now make sure we are not paused and continue the animation this._paused = false return this._continue() - } pause () { - // Cancel the next animation frame and pause this._nextFrame = null this._paused = true return this - } stop () { - // Cancel the next animation frame and go to start - this.seek( -this._time ) + this.seek(-this._time) return this.pause() - } finish () { - - this.seek( Infinity ) + this.seek(Infinity) return this.pause() - } - speed ( speed ) { - - if ( speed == null ) return this._speed + speed (speed) { + if (speed == null) return this._speed this._speed = speed return this - } - reverse ( yes ) { - + reverse (yes) { var currentSpeed = this.speed() - if ( yes == null ) return this.speed( -currentSpeed ) - - var positive = Math.abs( currentSpeed ) - return this.speed( yes ? positive : -positive ) + if (yes == null) return this.speed(-currentSpeed) + var positive = Math.abs(currentSpeed) + return this.speed(yes ? positive : -positive) } - seek ( dt ) { - + seek (dt) { this._time += dt return this._continue() - } - time ( time ) { - - if ( time == null ) return this._time + time (time) { + if (time == null) return this._time this._time = time return this - } - persist ( dtOrForever ) { - - if ( dtOrForever == null ) return this._persist + persist (dtOrForever) { + if (dtOrForever == null) return this._persist this._persist = dtOrForever return this - } - source ( fn ) { - - if ( fn == null ) return this._timeSource + source (fn) { + if (fn == null) return this._timeSource this._timeSource = fn return this - } _step () { - // If the timeline is paused, just do nothing - if ( this._paused ) return + if (this._paused) return // Get the time delta from the last time and update the time var time = this._timeSource() var dtSource = time - this._lastSourceTime - var dtTime = this._speed * dtSource + ( this._time - this._lastStepTime ) + var dtTime = this._speed * dtSource + (this._time - this._lastStepTime) this._lastSourceTime = time // Update the time @@ -245,8 +193,7 @@ export default class Timeline extends EventTarget { // Run all of the runners directly var runnersLeft = false - for ( var i = 0, len = this._order.length; i < len; i++ ) { - + for (var i = 0, len = this._order.length; i < len; i++) { // Get and run the current runner and ignore it if its inactive var runnerInfo = this._runners[this._order[i]] var runner = runnerInfo.runner @@ -257,89 +204,64 @@ export default class Timeline extends EventTarget { let dtToStart = this._time - runnerInfo.start // Dont run runner if not started yet - if ( dtToStart < 0 ) { - + if (dtToStart < 0) { runnersLeft = true continue - - } else if ( dtToStart < dt ) { - + } else if (dtToStart < dt) { // Adjust dt to make sure that animation is on point dt = dtToStart - } - if ( !runner.active() ) continue + if (!runner.active()) continue // If this runner is still going, signal that we need another animation // frame, otherwise, remove the completed runner - var finished = runner.step( dt ).done - if ( !finished ) { - + var finished = runner.step(dt).done + if (!finished) { runnersLeft = true // continue - - } else if ( runnerInfo.persist !== true ) { - + } else if (runnerInfo.persist !== true) { // runner is finished. And runner might get removed var endTime = runner.duration() - runner.time() + this._time - if ( endTime + this._persist < this._time ) { - + if (endTime + this._persist < this._time) { // Delete runner and correct index delete this._runners[this._order[i]] - this._order.splice( i--, 1 ) && --len - runner.timeline( null ) - + this._order.splice(i--, 1) && --len + runner.timeline(null) } - } - } // Get the next animation frame to keep the simulation going - if ( runnersLeft ) { - - this._nextFrame = Animator.frame( this._step.bind( this ) ) - + if (runnersLeft) { + this._nextFrame = Animator.frame(this._step.bind(this)) } else { - this._nextFrame = null - } return this - } // Checks if we are running and continues the animation _continue () { - - if ( this._paused ) return this - if ( !this._nextFrame ) { - - this._nextFrame = Animator.frame( this._step.bind( this ) ) - + if (this._paused) return this + if (!this._nextFrame) { + this._nextFrame = Animator.frame(this._step.bind(this)) } return this - } active () { - return !!this._nextFrame - } - } -registerMethods( { +registerMethods({ Element: { timeline: function () { - - this._timeline = ( this._timeline || new Timeline() ) + this._timeline = (this._timeline || new Timeline()) return this._timeline - } } -} ) +}) |