diff options
author | Ulrich-Matthias Schäfer <ulima.ums@googlemail.com> | 2018-05-24 23:42:01 +0200 |
---|---|---|
committer | Ulrich-Matthias Schäfer <ulima.ums@googlemail.com> | 2018-05-24 23:42:01 +0200 |
commit | 4d39baa3e4191c70d3eb7c9b67704b29f79a812d (patch) | |
tree | 36540bcb48b8e4be66fe8332b0502eb3d1218815 /src | |
parent | ebf2a8bb395b78b5bc513fb1ec17e1222dcb0f1d (diff) | |
download | svg.js-4d39baa3e4191c70d3eb7c9b67704b29f79a812d.tar.gz svg.js-4d39baa3e4191c70d3eb7c9b67704b29f79a812d.zip |
fixed some more errores, make declaritive controllers partially work. added PID controller for testing reasons
Diffstat (limited to 'src')
-rw-r--r-- | src/controller.js | 35 | ||||
-rw-r--r-- | src/morph.js | 7 | ||||
-rw-r--r-- | src/runner.js | 42 | ||||
-rw-r--r-- | src/timeline.js | 39 |
4 files changed, 67 insertions, 56 deletions
diff --git a/src/controller.js b/src/controller.js index fdb26f7..f6fab93 100644 --- a/src/controller.js +++ b/src/controller.js @@ -81,16 +81,21 @@ SVG.Controller = SVG.invent ({ create: function (fn) { SVG.Stepper.call(this, fn) + this.stepper = fn }, extend: { step: function (current, target, dt, c) { - + return this.stepper(current, target, dt, c) }, isComplete: function (dt, c) { - + var result = false + for(var i = c.length; i--;) { + result = result || (Math.abs(c[i].error) < 0.01) + } + return result }, }, }) @@ -129,3 +134,29 @@ SVG.Spring = function spring(duration, overshoot) { return newPosition }) } + +SVG.PID = function (P, I, D, antiwindup) { + P = P == null ? 0.1 : P + I = I == null ? 0.01 : I + D = D == null ? 0 : D + antiwindup = antiwindup == null ? 1000 : antiwindup + + // Return the acceleration required + return new SVG.Controller( + function (current, target, dt, c) { + + if(dt == Infinity) return target + + var p = target - current + var i = (c.integral || 0) + p * dt + var d = (p - (c.error || 0)) / dt + + // antiwindup + i = Math.max(-antiwindup, Math.min(i, antiwindup)) + + c.error = p + c.integral = i + + return current + (P * p + I * i + D * d) + }) +} diff --git a/src/morph.js b/src/morph.js index c6e2152..8bb6fbd 100644 --- a/src/morph.js +++ b/src/morph.js @@ -72,10 +72,9 @@ SVG.Morphable = SVG.invent({ } else { this.type(SVG.Morphable.NonMorphable) - } - } else if (value in SVG.MorphableTypes) { + } else if (SVG.MorphableTypes.indexOf(value.constructor) > -1) { this.type(value.constructor) } else if (Array.isArray(value)) { @@ -102,7 +101,7 @@ SVG.Morphable = SVG.invent({ // FIXME: we can call this._stepper.isComplete directly // no need for this wrapper here isComplete: function () { - return this._stepper && this._stepper.isComplete() + return this._stepper && this._stepper.isComplete(null, this._context) }, at: function (pos) { @@ -115,7 +114,7 @@ SVG.Morphable = SVG.invent({ return this._type.prototype.fromArray( this.modifier( this._from.map(function (i, index) { - return _this._stepper.step(i, _this._to[index], pos, _this._context[i]) + return _this._stepper.step(i, _this._to[index], pos, _this._context[index]) }) ) ) diff --git a/src/runner.js b/src/runner.js index 9ed5bbb..718c5c8 100644 --- a/src/runner.js +++ b/src/runner.js @@ -27,14 +27,14 @@ SVG.Runner = SVG.invent({ // Work out the stepper and the duration this._duration = typeof options === 'number' && options - this._isDeclaritive = options instanceof SVG.Controller - this._stepper = this._isDeclaritive ? options : new SVG.Ease() + this._isDeclarative = options instanceof SVG.Controller + this._stepper = this._isDeclarative ? options : new SVG.Ease() // We copy the current values from the timeline because they can change this._morphers = {} // Store the state of the runner - this._enabled = true + this.enabled = true this._time = 0 this._last = 0 this.tags = {} @@ -50,7 +50,7 @@ SVG.Runner = SVG.invent({ var waits = [] // If we have an object, unpack the values - if (typeof duration == 'object') { + if (typeof duration == 'object' && !(duration instanceof SVG.Stepper)) { delay = duration.delay || 0 when = duration.when || 'now' duration = duration.duration || 1000 @@ -169,19 +169,25 @@ SVG.Runner = SVG.invent({ step: function (dt) { + // FIXME: It makes more sense to have this in the timeline + // because the user should still ne able to step a runner + // even if disabled + // Don't bother running when not enabled + if(!this.enabled) return false + // If there is no duration, we are in declarative mode and dt has to be // positive always, so if its negative, we ignore it. - if ( this._isDeclarative && dt < 0 ) return false + if (this._isDeclarative && dt < 0) return false // Increment the time and read out the parameters var duration = this._duration - this._time += dt || 16 + this._time += dt || 16 // FIXME: step(0) is valid but will get changed to 16 here var time = this._time // Work out if we are in range to run the function var timeInside = 0 <= time && time <= duration var position = time / duration - var finished = time >= duration + var finished = !this._isDeclarative && time >= duration // TODO: clean this up. finished returns true even for declarative if we do not check for it explicitly // If we are on the rising edge, initialise everything, otherwise, // initialise only what needs to be initialised on the rising edge @@ -192,16 +198,16 @@ SVG.Runner = SVG.invent({ this._last = time // If we haven't started yet or we are over the time, just exit - if(!timeInside && !justFinished) return finished + if(!this._isDeclarative && !timeInside && !justFinished) return finished // TODO: same as above // Run the runner and store the last time it was run finished = this._run( - duration === null ? dt // No duration, declarative + this._isDeclarative ? dt // No duration, declarative : finished ? 1 // If completed, provide 1 : position // If running, ) || finished - // FIXME: for the sake of unifirmity this method should return This + // FIXME: for the sake of conformity this method should return this // we can then add a functon isFinished to see if a runner is finished // Work out if we are finished return finished @@ -225,8 +231,8 @@ SVG.Runner = SVG.invent({ }, active: function (enabled) { - if(enabled == null) return this._enabled - this._enabled = enabled + if(enabled == null) return this.enabled + this.enabled = enabled return this }, @@ -249,7 +255,12 @@ SVG.Runner = SVG.invent({ }, untag: function (name) { + name = Array.isArray(name) ? name : [name] + for(var i = name.length; i--;) { + delete this.tags[name[i]] + } + return this }, /* @@ -288,6 +299,10 @@ SVG.Runner = SVG.invent({ // Run each run function for the position given _run: function (position) { + // TODO: review this one + // Make sure to keep runner running when no functions where added yet + if(!this._functions.length) return false + // Run all of the _functions directly var allfinished = false for (var i = 0, len = this._functions.length; i < len ; ++i) { @@ -313,7 +328,6 @@ SVG.Runner = SVG.invent({ // Timeline class above SVG.extend(SVG.Runner, { - attr: function (a, v) { return this.styleAttr('attr', a, v) }, @@ -497,8 +511,10 @@ SVG.extend(SVG.Runner, { // Make a morpher and queue the animation var morpher = new SVG.Morphable(this._stepper).to(to) this.queue(function () { + console.log('init') morpher.from(this[method]()) }, function (pos) { + console.log('run', pos) this[method](morpher.at(pos)) return morpher.isComplete() }, this._isDeclarative) diff --git a/src/timeline.js b/src/timeline.js index 5bdcb55..9ed6b74 100644 --- a/src/timeline.js +++ b/src/timeline.js @@ -132,6 +132,7 @@ SVG.Timeline = SVG.invent({ // derived from the current timeline time or it can be relative to the // last start time to chain animations direclty var absoluteStartTime + delay = delay || 0 // Work out when to start the animation if ( when == null || when === 'last' || when === 'relative' ) { @@ -154,43 +155,6 @@ SVG.Timeline = SVG.invent({ this._step() return this - - - - // Clear the controller and the looping parameters - this._controller = duration instanceof Function ? duration : null - this._backwards = false - this._swing = false - this._loops = 0 - - // If we have an object we are declaring imperative animations - if (typeof duration === 'object') { - duration = duration.duration - delay = duration.delay - nowOrAbsolute = duration.absolute || duration.now - } - - // The start time for the next animation can either be given explicitly, - // derived from the current timeline time or it can be relative to the - // last start time to chain animations direclty - var absoluteStartTime = typeof nowOrAbsolute === 'number' ? nowOrAbsolute - : nowOrAbsolute ? this._time - : this._startTime + this._duration - - // We start the next animation after the delay required - this._startTime = absoluteStartTime + (delay || 0) - this._duration = duration instanceof Function ? null - : (duration || SVG.defaults.timeline.duration) - - // Make a new runner to queue all of the animations onto - this._runner = new Runner(this._time - this._startTime, this.duration) - this._runners.push(this._runner) - - // Step the animation - this._step() - - // Allow for chaining - return this }, play () { @@ -286,6 +250,7 @@ SVG.Timeline = SVG.invent({ // Get and run the current runner and figure out if its done running var runner = this._runners[i] + var finished = runner.step(dt) // If this runner is still going, signal that we need another animation |