From 62de7d0a1b994b69032a759b796b486e6bc382e3 Mon Sep 17 00:00:00 2001 From: Saivan Date: Sun, 25 Nov 2018 16:21:53 +1300 Subject: Changed the esLint rules to avoid silly ternary operators, and to let code breathe! This commit modifies some of the eslint rules, to allow our code to be a little bit more readable. This came about because we had a particularly pesky problem, where the code was indenting ternary operators. This fixes that, and makes it easy to add new rules to eslint as we please in the future. Changes ======= - Rebuilt the library with new eslint rules - Changed the eslintrc file to a yaml file by default --- src/animation/Runner.js | 842 +++++++++++++++++++++++++++++++----------------- 1 file changed, 547 insertions(+), 295 deletions(-) (limited to 'src/animation/Runner.js') diff --git a/src/animation/Runner.js b/src/animation/Runner.js index 47929fd..d2c7bdf 100644 --- a/src/animation/Runner.js +++ b/src/animation/Runner.js @@ -15,7 +15,9 @@ 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 @@ -28,7 +30,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 @@ -61,6 +63,7 @@ export default class Runner extends EventTarget { this._swing = false this._wait = 0 this._times = 1 + } /* @@ -70,58 +73,75 @@ 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 @@ -129,10 +149,13 @@ 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 ) + } /* @@ -141,26 +164,32 @@ 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 ) + } /* @@ -169,34 +198,45 @@ 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 @@ -206,7 +246,8 @@ 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 @@ -215,40 +256,49 @@ 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 @@ -264,8 +314,10 @@ 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 @@ -275,41 +327,54 @@ 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 + } /* @@ -319,102 +384,135 @@ 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) - // for everything else a simple morpher change is sufficient + 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 @@ -424,13 +522,15 @@ 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 { @@ -441,215 +541,285 @@ 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) - let index = this.ids.indexOf(leftSibling) + 1 + }, 0 ) - this.ids.splice(index, 0, id) - this.runners.splice(index, 0, runner) + let index = this.ids.indexOf( leftSibling ) + 1 + + 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) + var morpher = new Morphable( this._stepper ).to( val ) + + this.queue( function () { + + morpher = morpher.from( this.element()[type]( name ) ) + + }, function ( pos ) { - this.queue(function () { - morpher = morpher.from(this.element()[type](name)) - }, function (pos) { - this.element()[type](name, morpher.at(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)) + zoom ( level, point ) { + + var morpher = new Morphable( this._stepper ).to( new SVGNumber( level ) ) + + this.queue( function () { - this.queue(function () { - morpher = morpher.from(this.zoom()) - }, function (pos) { - this.element().zoom(morpher.at(pos), point) + morpher = morpher.from( this.zoom() ) + + }, function ( pos ) { + + this.element().zoom( morpher.at( pos ), point ) return morpher.done() - }) + + } ) return this + }, /** @@ -669,22 +839,25 @@ 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 @@ -693,249 +866,328 @@ 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 const rCurrent = start.rotate // 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 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 ) 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) + var morpher = this._element.MorphArray().to( a ) + + this.queue( function () { + + morpher.from( this._element.array() ) - this.queue(function () { - morpher.from(this._element.array()) - }, function (pos) { - this._element.plot(morpher.at(pos)) - }) + }, 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 } ) -- cgit v1.2.3