summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUlrich-Matthias Schäfer <ulima.ums@googlemail.com>2018-10-17 23:09:34 +0200
committerUlrich-Matthias Schäfer <ulima.ums@googlemail.com>2018-10-17 23:09:34 +0200
commit417d4b253d2daea0ef3c437c5b3d5eda6ccc7525 (patch)
tree1b5e6528df2cd679af07e4ffc44c177ed35dac68 /src
parent8db39b099ea85d881f5e4d12b2b2182d41414da4 (diff)
downloadsvg.js-417d4b253d2daea0ef3c437c5b3d5eda6ccc7525.tar.gz
svg.js-417d4b253d2daea0ef3c437c5b3d5eda6ccc7525.zip
add babel, satisfy linter, build dist
Diffstat (limited to 'src')
-rw-r--r--src/controller.js67
-rw-r--r--src/helpers.js16
-rw-r--r--src/matrix.js11
-rw-r--r--src/morph.js180
-rw-r--r--src/runner.js270
-rw-r--r--src/svg.js2
-rw-r--r--src/timeline.js91
-rw-r--r--src/transform.js2
8 files changed, 237 insertions, 402 deletions
diff --git a/src/controller.js b/src/controller.js
index 46c1771..842c772 100644
--- a/src/controller.js
+++ b/src/controller.js
@@ -18,8 +18,8 @@ function makeSetterGetter (k, f) {
}
}
-SVG.Stepper = SVG.invent ({
- create: function () {},
+SVG.Stepper = SVG.invent({
+ create: function () {}
})
/***
@@ -27,8 +27,7 @@ Easing Functions
================
***/
-SVG.Ease = SVG.invent ({
-
+SVG.Ease = SVG.invent({
inherit: SVG.Stepper,
create: function (fn) {
@@ -40,7 +39,7 @@ SVG.Ease = SVG.invent ({
extend: {
step: function (from, to, pos) {
- if(typeof from !== 'number') {
+ if (typeof from !== 'number') {
return pos < 1 ? from : to
}
return from + (to - from) * this.ease(pos)
@@ -48,8 +47,8 @@ SVG.Ease = SVG.invent ({
done: function (dt, c) {
return false
- },
- },
+ }
+ }
})
SVG.easing = {
@@ -61,17 +60,15 @@ SVG.easing = {
return function (t) {
// TODO: FINISH
}
- },
+ }
}
-
/***
Controller Types
================
***/
-SVG.Controller = SVG.invent ({
-
+SVG.Controller = SVG.invent({
inherit: SVG.Stepper,
create: function (fn) {
@@ -87,12 +84,11 @@ SVG.Controller = SVG.invent ({
done: function (c) {
return c.done
- },
- },
+ }
+ }
})
function recalculate () {
-
// Apply the default parameters
var duration = (this._duration || 500) / 1000
var overshoot = this._overshoot || 0
@@ -101,15 +97,15 @@ function recalculate () {
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 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
}
-SVG.Spring = SVG.invent ({
+SVG.Spring = SVG.invent({
inherit: SVG.Controller,
create: function (duration, overshoot) {
@@ -119,11 +115,10 @@ SVG.Spring = SVG.invent ({
extend: {
step: function (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 (typeof current === 'string') return current
+ c.done = dt === Infinity
+ if (dt === Infinity) return target
+ if (dt === 0) return current
if (dt > 100) dt = 16
@@ -133,10 +128,10 @@ SVG.Spring = SVG.invent ({
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 newPosition = current
- + velocity * dt
- + acceleration * dt * dt / 2
+ var acceleration = -this.d * velocity - this.k * (current - target)
+ var newPosition = current +
+ velocity * dt +
+ acceleration * dt * dt / 2
// Store the velocity
c.velocity = velocity + acceleration * dt
@@ -147,16 +142,14 @@ SVG.Spring = SVG.invent ({
},
duration: makeSetterGetter('_duration', recalculate),
- overshoot: makeSetterGetter('_overshoot', recalculate),
+ overshoot: makeSetterGetter('_overshoot', recalculate)
}
})
-SVG.PID = SVG.invent ({
+SVG.PID = SVG.invent({
inherit: SVG.Controller,
create: function (p, i, d, windup) {
- if(!(this instanceof SVG.PID))
- return new SVG.PID(p, i, d, windup)
SVG.Controller.call(this)
p = p == null ? 0.1 : p
@@ -168,12 +161,11 @@ SVG.PID = SVG.invent ({
extend: {
step: function (current, target, dt, c) {
+ if (typeof current === 'string') return current
+ c.done = dt === Infinity
- 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
@@ -181,8 +173,9 @@ SVG.PID = SVG.invent ({
var windup = this.windup
// antiwindup
- if(windup !== false)
+ if (windup !== false) {
i = Math.max(-windup, Math.min(i, windup))
+ }
c.error = p
c.integral = i
@@ -195,6 +188,6 @@ SVG.PID = SVG.invent ({
windup: makeSetterGetter('windup'),
p: makeSetterGetter('P'),
i: makeSetterGetter('I'),
- d: makeSetterGetter('D'),
+ d: makeSetterGetter('D')
}
})
diff --git a/src/helpers.js b/src/helpers.js
index fc22e4c..c2073cf 100644
--- a/src/helpers.js
+++ b/src/helpers.js
@@ -254,12 +254,10 @@ function formatTransforms (o) {
// Populate all of the values
return {
- scaleX, scaleY, skewX, skewY, shear, theta,
- rx, ry, tx, ty, ox, oy, px, py
+ scaleX, scaleY, skewX, skewY, shear, theta, rx, ry, tx, ty, ox, oy, px, py
}
}
-
// left matrix, right matrix, target matrix which is overwritten
function matrixMultiply (l, r, o) {
// Work out the product directly
@@ -281,15 +279,13 @@ function matrixMultiply (l, r, o) {
return o
}
-
-function getOrigin (o, element, inSpace) {
+function getOrigin (o, element) {
// Allow origin or around as the names
let origin = o.origin // o.around == null ? o.origin : o.around
let ox, oy
// Allow the user to pass a string to rotate around a given point
if (typeof origin === 'string' || origin == null) {
-
// Get the bounding box of the element with no transformations applied
const string = (origin || 'center').toLowerCase().trim()
const { height, width, x, y } = element.bbox()
@@ -305,19 +301,11 @@ function getOrigin (o, element, inSpace) {
// Set the bounds eg : "bottom-left", "Top right", "middle" etc...
ox = o.ox != null ? o.ox : bx
oy = o.oy != null ? o.oy : by
-
} else {
ox = origin[0]
oy = origin[1]
}
- // Transform the origin into the current reference frame
- if ( inSpace ) {
- let originRelative = new SVG.Point( ox, oy ).transform(inSpace)
- ox = originRelative.x
- oy = originRelative.y
- }
-
// Return the origin as it is if it wasn't a string
return [ ox, oy ]
}
diff --git a/src/matrix.js b/src/matrix.js
index 49015a3..666b898 100644
--- a/src/matrix.js
+++ b/src/matrix.js
@@ -1,4 +1,4 @@
-/* global abcdef, arrayToMatrix, closeEnough, formatTransforms */
+/* global abcdef arrayToMatrix closeEnough formatTransforms isMatrixLike matrixMultiply */
SVG.Matrix = SVG.invent({
// Initialize
@@ -41,7 +41,7 @@ SVG.Matrix = SVG.invent({
// Get the proposed transformations and the current transformations
var t = formatTransforms(o)
- var current = this//new SVG.Matrix(this) // FIXME: do we need a new matrix here?
+ var current = this
let { x: ox, y: oy } = new SVG.Point(t.ox, t.oy).transform(current)
// Construct the resulting matrix
@@ -260,7 +260,7 @@ SVG.Matrix = SVG.invent({
scaleO: function (x, y = x, cx = 0, cy = 0) {
// Support uniform scaling
- if (arguments.length == 3) {
+ if (arguments.length === 3) {
cy = cx
cx = y
y = x
@@ -335,7 +335,7 @@ SVG.Matrix = SVG.invent({
skewO: function (x, y = x, cx = 0, cy = 0) {
// support uniformal skew
- if (arguments.length == 3) {
+ if (arguments.length === 3) {
cy = cx
cx = y
y = x
@@ -467,9 +467,6 @@ SVG.Matrix = SVG.invent({
//
// SVG.extend(SVG.Matrix, extensions)
-
-
-
// function matrixMultiplyParams (matrix, a, b, c, d, e, f) {
// return matrixMultiply({a, b, c, d, e, f}, matrix, matrix)
// }
diff --git a/src/morph.js b/src/morph.js
index bf94efc..acb9e21 100644
--- a/src/morph.js
+++ b/src/morph.js
@@ -14,16 +14,18 @@ SVG.Morphable = SVG.invent({
extend: {
from: function (val) {
- if(val == null)
+ if (val == null) {
return this._from
+ }
this._from = this._set(val)
return this
},
to: function (val) {
- if(val == null)
+ if (val == null) {
return this._to
+ }
this._to = this._set(val)
return this
@@ -31,8 +33,9 @@ SVG.Morphable = SVG.invent({
type: function (type) {
// getter
- if (type == null)
+ if (type == null) {
return this._type
+ }
// setter
this._type = type
@@ -40,40 +43,30 @@ SVG.Morphable = SVG.invent({
},
_set: function (value) {
-
- if(!this._type) {
+ if (!this._type) {
var type = typeof value
if (type === 'number') {
this.type(SVG.Number)
-
} else if (type === 'string') {
-
if (SVG.Color.isColor(value)) {
this.type(SVG.Color)
-
} else if (SVG.regex.delimiter.test(value)) {
this.type(SVG.regex.pathLetters.test(value)
? SVG.PathArray
: SVG.Array
)
-
} else if (SVG.regex.numberAndUnit.test(value)) {
this.type(SVG.Number)
-
} else {
this.type(SVG.Morphable.NonMorphable)
}
-
} else if (SVG.MorphableTypes.indexOf(value.constructor) > -1) {
this.type(value.constructor)
-
} else if (Array.isArray(value)) {
this.type(SVG.Array)
-
} else if (type === 'object') {
this.type(SVG.Morphable.ObjectBag)
-
} else {
this.type(SVG.Morphable.NonMorphable)
}
@@ -81,13 +74,13 @@ SVG.Morphable = SVG.invent({
var result = (new this._type(value)).toArray()
this._morphObj = this._morphObj || new this._type()
- this._context = this._context
- || Array.apply(null, Array(result.length)).map(Object)
+ this._context = this._context ||
+ Array.apply(null, Array(result.length)).map(Object)
return result
},
stepper: function (stepper) {
- if(stepper == null) return this._stepper
+ if (stepper == null) return this._stepper
this._stepper = stepper
return this
},
@@ -132,7 +125,7 @@ SVG.Morphable.NonMorphable = SVG.invent({
SVG.Morphable.TransformBag = SVG.invent({
create: function (obj) {
- if(Array.isArray(obj)) {
+ if (Array.isArray(obj)) {
obj = {
scaleX: obj[0],
scaleY: obj[1],
@@ -149,7 +142,7 @@ SVG.Morphable.TransformBag = SVG.invent({
},
extend: {
- toArray: function (){
+ toArray: function () {
var v = this
return [
@@ -160,7 +153,7 @@ SVG.Morphable.TransformBag = SVG.invent({
v.translateX,
v.translateY,
v.originX,
- v.originY,
+ v.originY
]
}
}
@@ -177,64 +170,11 @@ SVG.Morphable.TransformBag.defaults = {
originY: 0
}
-// SVG.Morphable.TransformBag = SVG.invent({
-// inherit: SVG.Matrix,
-// create: function (obj) {
-// if(Array.isArray(obj)) {
-// obj = {
-// scaleX: obj[0],
-// scaleY: obj[1],
-// shear: obj[2],
-// rotate: obj[3],
-// translateX: obj[4],
-// translateY: obj[5],
-// originX: obj[6],
-// originY: obj[7]
-// }
-// }
-//
-// var data = {...(obj || {})}
-//
-// if (typeof data.origin == 'string') {
-// delete data.origin
-// }
-//
-// SVG.Matrix.call(this, data)
-//
-//
-// if (data.origin) {
-// data.originX = data.origin[0]
-// data.originY = data.origin[1]
-// }
-//
-// this.originX = data.originX || 0
-// this.originY = data.originY || 0
-// },
-//
-// extend: {
-// toArray: function (){
-// var v = this.decompose(this.originX, this.originY)
-//
-// return [
-// v.scaleX,
-// v.scaleY,
-// v.shear,
-// v.rotate,
-// v.translateX,
-// v.translateY,
-// v.originX,
-// v.originY,
-// ]
-// }
-// }
-// })
-
-
SVG.Morphable.ObjectBag = SVG.invent({
create: function (objOrArr) {
this.values = []
- if(Array.isArray(objOrArr)) {
+ if (Array.isArray(objOrArr)) {
this.values = objOrArr
return
}
@@ -251,14 +191,14 @@ SVG.Morphable.ObjectBag = SVG.invent({
var obj = {}
var arr = this.values
- for(var i = 0, len = arr.length; i < len; i+=2) {
- obj[arr[i]] = arr[i+1]
+ for (var i = 0, len = arr.length; i < len; i += 2) {
+ obj[arr[i]] = arr[i + 1]
}
return obj
},
- toArray: function (){
+ toArray: function () {
return this.values
}
}
@@ -274,7 +214,7 @@ SVG.MorphableTypes = [
SVG.PathArray,
SVG.Morphable.NonMorphable,
SVG.Morphable.TransformBag,
- SVG.Morphable.ObjectBag,
+ SVG.Morphable.ObjectBag
]
SVG.extend(SVG.MorphableTypes, {
@@ -285,89 +225,7 @@ SVG.extend(SVG.MorphableTypes, {
.to(val, args)
},
fromArray: function (arr) {
- this.constructor.call(this, arr)
+ this.constructor(arr)
return this
}
})
-
-
-
-
-// - Objects are just variable bags
-// - morph rerutrns a morphable. No state on normal objects (like SVG.Color)
-// - Objects can be represented as Array (with toArray())
-// - Objects have an unmorph/fromarray function which converts it back to a normal object
-
-// var b = new Color('#fff')
-// b.morph('#000') === new Morph(b).to('#000')
-
-// sweet = Color('#fff')
-// dark = Color('#fef')
-// sweet.to(dark, 'hsl')
-
-// angle = Number(30)
-// lastAngle = Number(300)
-// angle.to(lastAngle, cyclic)
-
-// mat1 = Matrix().transform({rotation: 30, scale: 0})
-// mat2 = Matrix(30, 40, 50, 60, 10, 20)
-// mat1.to(mat2)
-
-
-
-
-/**
-
-el.loop({times: 5, swing: true, wait: [20, 50]})
-
-el.opacity(0)
- .animate(300).opacity(1)
- .animate(300, true).scale(5).reverse()
-
-
-for(var i = 0; i < 7; ++i)
- circle.clone()
- .scale(3).rotate(0)
- .loop({swing: false, wait: 500})
- .scale(1)
- .rotate(360)
- .delay(1000)
- .animate(500, 'swingOut')
- .scale(3)
-}
-
-fn () => {
- el.animate().stroke('dashoffset', 213).scale(1)
- .delay(1)
- .animate().scale(2)
- .after(fn)
-}
-
-When you start an element has a base matrix B - which starts as the identity
-
- If you modify the matrix, then we have:
-
- T U V W X B x
- . . .
-
- runner.step()
-
- for all runners in stack:
- if(runner is done) repalce with matrix
-
- if(2 matrix next to eachother are done) {
-
- }
-
-What if
-
-/// RunnerA
-el.animate()
- .transform({rotate: 30, scale: 2})
- .transform({rotate: 500}, true)
-
-f| -----A-----
-s| --------B---------
-t| ---------C-------
-
-**/
diff --git a/src/runner.js b/src/runner.js
index 788563c..41280a0 100644
--- a/src/runner.js
+++ b/src/runner.js
@@ -1,3 +1,4 @@
+/* global isMatrixLike getOrigin */
SVG.easing = {
'-': function (pos) { return pos },
@@ -7,13 +8,10 @@ SVG.easing = {
}
SVG.Runner = SVG.invent({
-
- inherit: SVG.EventTarget,
parent: SVG.Element,
create: function (options) {
-
- // Store a unique id on the runner, so that we can identify it
+ // Store a unique id on the runner, so that we can identify it later
this.id = SVG.Runner.id++
// Ensure a default value
@@ -27,7 +25,6 @@ SVG.Runner = SVG.invent({
: options
// Declare all of the variables
- this._dispatcher = document.createElement('div')
this._element = null
this._timeline = null
this.done = false
@@ -74,7 +71,7 @@ SVG.Runner = SVG.invent({
delay: function (by, when) {
return this.animate(0, by, when)
- },
+ }
},
extend: {
@@ -87,7 +84,7 @@ SVG.Runner = SVG.invent({
*/
element: function (element) {
- if(element == null) return this._element
+ if (element == null) return this._element
this._element = element
element._prepareRunner()
return this
@@ -95,29 +92,29 @@ SVG.Runner = SVG.invent({
timeline: function (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: function(duration, delay, when) {
+ animate: function (duration, delay, when) {
var o = SVG.Runner.sanitise(duration, delay, when)
var runner = new SVG.Runner(o.duration)
- if(this._timeline) runner.timeline(this._timeline)
- if(this._element) runner.element(this._element)
+ if (this._timeline) runner.timeline(this._timeline)
+ if (this._element) runner.element(this._element)
return runner.loop(o).schedule(delay, when)
},
schedule: function (timeline, delay, when) {
// The user doesn't need to pass a timeline if we already have one
- if(!(timeline instanceof SVG.Timeline)) {
+ if (!(timeline instanceof SVG.Timeline)) {
when = delay
delay = timeline
timeline = this.timeline()
}
// If there is no timeline, yell at the user...
- if(!timeline) {
+ if (!timeline) {
throw Error('Runner cannot be scheduled without timeline')
}
@@ -163,7 +160,7 @@ SVG.Runner = SVG.invent({
runner: runFn || SVG.void,
isTransform: isTransform,
initialised: false,
- finished: false,
+ finished: false
})
var timeline = this.timeline()
timeline && this.timeline()._continue()
@@ -212,7 +209,6 @@ SVG.Runner = SVG.invent({
},
position: function (p) {
-
// Get all of the variables we need
var x = this._time
var d = this._duration
@@ -220,9 +216,9 @@ SVG.Runner = SVG.invent({
var t = this._times
var s = this._swing
var r = this._reverse
+ var position
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
@@ -231,7 +227,7 @@ SVG.Runner = SVG.invent({
*/
// Figure out the value without thinking about the start or end time
- function f (x) {
+ 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
@@ -241,7 +237,7 @@ SVG.Runner = SVG.invent({
// Figure out the value by incorporating the start time
var endTime = t * (w + d) - w
- var position = x <= 0 ? Math.round(f(1e-5))
+ position = x <= 0 ? Math.round(f(1e-5))
: x < endTime ? f(x)
: Math.round(f(endTime - 1e-5))
return position
@@ -249,9 +245,9 @@ SVG.Runner = SVG.invent({
// 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 swingForward = s && (loopsDone % 2 === 0)
var forwards = (swingForward && !r) || (r && swingForward)
- var position = loopsDone + (forwards ? p : 1 - p)
+ position = loopsDone + (forwards ? p : 1 - p)
return this.loops(position)
},
@@ -263,7 +259,6 @@ SVG.Runner = SVG.invent({
},
step: function (dt) {
-
// If we are inactive, this stepper just gets skipped
if (!this.enabled) return this
@@ -292,7 +287,7 @@ SVG.Runner = SVG.invent({
this.done = !declarative && !justFinished && this._time >= duration
// Call initialise and the run function
- if ( running || declarative ) {
+ if (running || declarative) {
this._initialise(running)
// clear the transforms on this runner so they dont get added again and again
@@ -324,7 +319,7 @@ SVG.Runner = SVG.invent({
},
active: function (enabled) {
- if(enabled == null) return this.enabled
+ if (enabled == null) return this.enabled
this.enabled = enabled
return this
},
@@ -341,7 +336,7 @@ SVG.Runner = SVG.invent({
// Add all of the tags to the object directly
name = Array.isArray(name) ? name : [name]
- for(var i = name.length; i--;) {
+ for (var i = name.length; i--;) {
this.tags[name[i]] = true
}
return this
@@ -349,7 +344,7 @@ SVG.Runner = SVG.invent({
untag: function (name) {
name = Array.isArray(name) ? name : [name]
- for(var i = name.length; i--;) {
+ for (var i = name.length; i--;) {
delete this.tags[name[i]]
}
return this
@@ -369,15 +364,14 @@ SVG.Runner = SVG.invent({
_rememberMorpher: function (method, morpher) {
this._history[method] = {
morpher: morpher,
- caller: this._queue[this._queue.length - 1],
+ 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: function (method, target) {
- if(this._history[method]) {
-
+ 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)
@@ -389,7 +383,6 @@ SVG.Runner = SVG.invent({
// which has access to the outer scope
if (this._history[method].caller.isTransform) {
this._history[method].caller.isTransform(target)
-
// for everything else a simple morpher change is sufficient
} else {
this._history[method].morpher.to(target)
@@ -405,18 +398,17 @@ SVG.Runner = SVG.invent({
// Run each initialise function in the runner if required
_initialise: function (running) {
-
// If we aren't running, we shouldn't initialise when not declarative
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 running = !current.finished
+ running = !current.finished
// Call the initialiser if we need to
if (needsIt && running) {
@@ -428,11 +420,9 @@ SVG.Runner = SVG.invent({
// Run each run function for the position or dt given
_run: function (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]
@@ -456,23 +446,22 @@ SVG.Runner = SVG.invent({
this.transforms = new SVG.Matrix()
return this
}
- },
+ }
})
SVG.Runner.id = 0
SVG.Runner.sanitise = function (duration, delay, when) {
-
// Initialise the default parameters
var times = 1
var swing = false
var wait = 0
- var duration = duration || SVG.defaults.timeline.duration
- var delay = delay || SVG.defaults.timeline.delay
- var when = when || 'last'
+ duration = duration || SVG.defaults.timeline.duration
+ delay = delay || SVG.defaults.timeline.delay
+ when = when || 'last'
// If we have an object, unpack the values
- if (typeof duration == 'object' && !(duration instanceof SVG.Stepper)) {
+ if (typeof duration === 'object' && !(duration instanceof SVG.Stepper)) {
delay = duration.delay || delay
when = duration.when || when
swing = duration.swing || swing
@@ -491,7 +480,6 @@ SVG.Runner.sanitise = function (duration, delay, when) {
}
}
-
SVG.FakeRunner = class {
constructor (transforms = new SVG.Matrix(), id = -1, done = true) {
this.transforms = transforms
@@ -509,79 +497,106 @@ SVG.extend([SVG.Runner, SVG.FakeRunner], {
}
})
+// SVG.FakeRunner.emptyRunner = new SVG.FakeRunner()
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
+ let runners = this._transformationRunners.runners
let netTransform = runners
.map(getRunnerTransform)
.reduce(lmultiply, new SVG.Matrix())
this.transform(netTransform)
- // Merge any two transformations in a row that are done
- let lastRunner = null
- runners.forEach((runner, i) => {
- if (lastRunner && runner.done && lastRunner.done) {
- delete runners[runner.id+1]
- runners[lastRunner.id+1] = runner.mergeWith(lastRunner)
- }
-
- lastRunner = runner
- })
+ this._transformationRunners.merge()
- // when the last runner is at index 0 it means all animations are done
- // that is because the first index always holds a FakeRunner and never an
- // actual Runner
- if (lastRunner == runners[0]) {
+ if (this._transformationRunners.length() === 1) {
this._frameId = null
}
-
- this._currentTransformCache = runners[0].transforms
}
+class RunnerArray {
+ constructor () {
+ this.runners = []
+ this.ids = []
+ }
-SVG.extend(SVG.Element, {
+ add (runner) {
+ if (this.runners.includes(runner)) return
- // 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: function (currentRunner) {
+ let id = runner.id + 1
- this._transformationRunners.forEach((runner, i, arr) => {
+ let leftSibling = this.ids.reduce((last, curr) => {
+ if (curr > last && curr < id) return curr
+ return last
+ }, 0)
- // only delete runners which run before the current
- if (runner.id < currentRunner.id) {
+ let index = this.ids.indexOf(leftSibling) + 1
- // if the runner is still running, it will add itself back on every
- // frame. So make sure to delete the transformations from this runner
- // so it doesnt interfer anymore
- if (!runner.done) {
- runner._queue = runner._queue.filter((item) => {
- return !item.isTransform
- })
- }
+ this.ids.splice(index, 0, id)
+ this.runners.splice(index, 0, runner)
- delete arr[i]
+ return this
+ }
+
+ 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)
+ 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))
}
+
+ lastRunner = runner
})
- this._transformationRunners[0] = new SVG.FakeRunner()
- },
+ return this
+ }
+
+ 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
+ }
- addToCurrentTransform (transform) {
- this._currentTransformCache = this._currentTransformCache.lmultiply(transform)
+ clearBefore (id) {
+ let deleteCnt = this.ids.indexOf(id + 1) || 1
+ this.ids.splice(0, deleteCnt, 0)
+ this.runners.splice(0, deleteCnt, new SVG.FakeRunner())
return this
+ }
+}
+
+SVG.extend(SVG.Element, {
+ // 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: function (currentRunner) {
+ this._transformationRunners.clearBefore(currentRunner.id)
},
_currentTransform (current) {
- // return this._currentTransformCache
- return this._transformationRunners
+ 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
@@ -591,7 +606,7 @@ SVG.extend(SVG.Element, {
},
addRunner: function (runner) {
- this._transformationRunners[runner.id+1] = runner
+ this._transformationRunners.add(runner)
SVG.Animator.transform_frame(
mergeTransforms.bind(this), this._frameId
@@ -600,20 +615,17 @@ SVG.extend(SVG.Element, {
_prepareRunner: function () {
if (this._frameId == null) {
- this._transformationRunners = [
- new SVG.FakeRunner(new SVG.Matrix(this))
- ]
+ this._transformationRunners = new RunnerArray()
+ .add(new SVG.FakeRunner(new SVG.Matrix(this)))
- // this._currentTransformCache = new SVG.Matrix(this)
this._frameId = SVG.Element.frameId++
}
- },
+ }
})
SVG.Element.frameId = 0
SVG.extend(SVG.Runner, {
-
attr: function (a, v) {
return this.styleAttr('attr', a, v)
},
@@ -644,17 +656,17 @@ SVG.extend(SVG.Runner, {
},
zoom: function (level, point) {
- var morpher = new SVG.Morphable(this._stepper).to(new SVG.Number(level))
+ var morpher = new SVG.Morphable(this._stepper).to(new SVG.Number(level))
- this.queue(function() {
- morpher = morpher.from(this.zoom())
- }, function (pos) {
- this.element().zoom(morpher.at(pos), point)
- return morpher.done()
- })
+ this.queue(function () {
+ morpher = morpher.from(this.zoom())
+ }, function (pos) {
+ this.element().zoom(morpher.at(pos), point)
+ return morpher.done()
+ })
- return this
- },
+ return this
+ },
/**
** absolute transformations
@@ -688,7 +700,7 @@ SVG.extend(SVG.Runner, {
// Create a morepher and set its type
const morpher = new SVG.Morphable()
- .type( affine ? SVG.Morphable.TransformBag : SVG.Matrix )
+ .type(affine ? SVG.Morphable.TransformBag : SVG.Matrix)
.stepper(this._stepper)
let origin
@@ -698,7 +710,6 @@ SVG.extend(SVG.Runner, {
let startTransform
function setup () {
-
// make sure element and origin is defined
element = element || this.element()
origin = origin || getOrigin(transforms, element)
@@ -709,13 +720,12 @@ SVG.extend(SVG.Runner, {
element.addRunner(this)
// Deactivate all transforms that have run so far if we are absolute
- if ( !relative ) {
+ if (!relative) {
element._clearTransformRunnersBefore(this)
}
}
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()
@@ -737,7 +747,7 @@ SVG.extend(SVG.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 distances = possibilities.map(a => Math.abs(a - rCurrent))
const shortest = Math.min(...distances)
const index = distances.indexOf(shortest)
target.rotate = possibilities[index]
@@ -766,13 +776,12 @@ SVG.extend(SVG.Runner, {
}
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
@@ -803,29 +812,28 @@ SVG.extend(SVG.Runner, {
},
_queueNumberDelta: function (method, to) {
- to = new SVG.Number(to)
-
- // Try to change the target if we have this method already registerd
- if (this._tryRetargetDelta(method, to)) return this
-
- // Make a morpher and queue the animation
- var morpher = new SVG.Morphable(this._stepper).to(to)
- this.queue(function () {
- var from = this.element()[method]()
- morpher.from(from)
- morpher.to(from + x)
- }, function (pos) {
- this.element()[method](morpher.at(pos))
- return morpher.done()
- })
+ to = new SVG.Number(to)
- // Register the morpher so that if it is changed again, we can retarget it
- this._rememberMorpher(method, morpher)
- return this
+ // Try to change the target if we have this method already registerd
+ if (this._tryRetargetDelta(method, to)) return this
+
+ // Make a morpher and queue the animation
+ var morpher = new SVG.Morphable(this._stepper).to(to)
+ this.queue(function () {
+ var from = this.element()[method]()
+ morpher.from(from)
+ morpher.to(from + to)
+ }, 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)
+ return this
},
_queueObject: function (method, to) {
-
// Try to change the target if we have this method already registerd
if (this._tryRetarget(method, to)) return this
@@ -910,7 +918,8 @@ SVG.extend(SVG.Runner, {
// in the init function
return this._queueObject('plot', new this._element.MorphArray(a))
- /*var morpher = this._element.morphArray().to(a)
+ /*
+ var morpher = this._element.morphArray().to(a)
this.queue(function () {
morpher.from(this._element.array())
@@ -918,7 +927,8 @@ SVG.extend(SVG.Runner, {
this._element.plot(morpher.at(pos))
})
- return this*/
+ return this
+ */
},
// Add leading method
diff --git a/src/svg.js b/src/svg.js
index c29d671..bf02df0 100644
--- a/src/svg.js
+++ b/src/svg.js
@@ -2,7 +2,7 @@
/* eslint-disable new-cap */
// The main wrapping element
-var SVG = this.SVG = function (element) {
+var SVG = window.SVG = function (element) {
if (SVG.supported) {
element = createElement(element)
return element
diff --git a/src/timeline.js b/src/timeline.js
index 02de178..0bf8ac5 100644
--- a/src/timeline.js
+++ b/src/timeline.js
@@ -7,7 +7,7 @@ SVG.easing = {
'<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 }
}
-var time = performance || Date
+var time = window.performance || Date
var makeSchedule = function (runnerInfo) {
var start = runnerInfo.start
@@ -57,10 +57,9 @@ SVG.Timeline = SVG.invent({
// schedules a runner on the timeline
schedule (runner, delay, when) {
-
- if(runner == null) {
+ if (runner == null) {
return this._runners.map(makeSchedule).sort(function (a, b) {
- return (a.start - b.start) || (a.duration - b.duration)
+ return (a.start - b.start) || (a.duration - b.duration)
})
}
@@ -80,50 +79,47 @@ SVG.Timeline = SVG.invent({
// Work out when to start the animation
if (when == null || when === 'last' || when === 'after') {
// Take the last time and increment
- absoluteStartTime = this._startTime //+ delay
-
- } else if (when === 'absolute' || when === 'start' ) {
+ absoluteStartTime = this._startTime
+ } else if (when === 'absolute' || when === 'start') {
absoluteStartTime = delay
delay = 0
-
} else if (when === 'now') {
- absoluteStartTime = this._time //+ delay
-
+ absoluteStartTime = this._time
} else if (when === 'relative') {
let runnerInfo = this._runners[runner.id]
if (runnerInfo) {
absoluteStartTime = runnerInfo.start + delay
delay = 0
}
-
} else {
throw new Error('Invalid value for the "when" parameter')
}
- // manage runner
+ // Manage runner
runner.unschedule()
runner.timeline(this)
runner.time(-delay)
- // save startTime for next runner
+ // Save startTime for next runner
this._startTime = absoluteStartTime + runner.duration() + delay
- // save runnerInfo
+ // Save runnerInfo
this._runners[runner.id] = {
persist: this.persist(),
runner: runner,
start: absoluteStartTime
}
- // save order and continue
+
+ // Save order and continue
this._order.push(runner.id)
this._continue()
return this
},
- // remove the runner from this timeline
+ // Remove the runner from this timeline
unschedule (runner) {
var index = this._order.indexOf(runner.id)
- if(index < 0) return this
+ if (index < 0) return this
delete this._runners[runner.id]
this._order.splice(index, 1)
@@ -132,7 +128,6 @@ SVG.Timeline = SVG.invent({
},
play () {
-
// Now make sure we are not paused and continue the animation
this._paused = false
return this._continue()
@@ -157,14 +152,14 @@ SVG.Timeline = SVG.invent({
},
speed (speed) {
- if(speed == null) return this._speed
+ if (speed == null) return this._speed
this._speed = speed
return this
},
reverse (yes) {
var currentSpeed = this.speed()
- if(yes == null) return this.speed(-currentSpeed)
+ if (yes == null) return this.speed(-currentSpeed)
var positive = Math.abs(currentSpeed)
return this.speed(yes ? positive : -positive)
@@ -176,7 +171,7 @@ SVG.Timeline = SVG.invent({
},
time (time) {
- if(time == null) return this._time
+ if (time == null) return this._time
this._time = time
return this
},
@@ -194,7 +189,6 @@ SVG.Timeline = SVG.invent({
},
_step () {
-
// If the timeline is paused, just do nothing
if (this._paused) return
@@ -218,15 +212,16 @@ SVG.Timeline = SVG.invent({
var runner = runnerInfo.runner
let dt = dtTime
- // Make sure that we give the actual dt to the start if needed
+ // Make sure that we give the actual difference
+ // between runner start time and now
let dtToStart = this._time - runnerInfo.start
- // dont run runner if not started yet
+ // Dont run runner if not started yet
if (dtToStart < 0) {
runnersLeft = true
continue
- } else if (dtToStart < dt){
- // adjust dt to make sure that animation is on point
+ } else if (dtToStart < dt) {
+ // Adjust dt to make sure that animation is on point
dt = dtToStart
}
@@ -238,42 +233,36 @@ SVG.Timeline = SVG.invent({
if (!finished) {
runnersLeft = true
// continue
+ } else if (runnerInfo.persist !== true) {
+ // runner is finished. And runner might get removed
+
+ // TODO: Figure out end time of runner
+ var endTime = runner.duration() - runner.time() + 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)
+ }
}
-
-
- // } else if(runnerInfo.persist !== true){
- //
- // // runner is finished. And runner might get removed
- //
- // // TODO: Figure out end time of runner
- // var endTime = runner.duration() - runner.time() + this._time
- //
- // if(endTime + this._persist < this._time) {
- // // FIXME: which one is better?
- // // runner.unschedule()
- // // --i
- // // --len
- //
- // // delete runner and correct index
- // this._runners.splice(i--, 1) && --len
- // runner.timeline(null)
- // }
- //
- // }
}
// Get the next animation frame to keep the simulation going
- if (runnersLeft)
+ if (runnersLeft) {
this._nextFrame = SVG.Animator.frame(this._step.bind(this))
- else this._nextFrame = null
+ } else {
+ this._nextFrame = null
+ }
return this
},
// Checks if we are running and continues the animation
_continue () {
if (this._paused) return this
- if (!this._nextFrame)
+ if (!this._nextFrame) {
this._nextFrame = SVG.Animator.frame(this._step.bind(this))
+ }
return this
},
@@ -288,6 +277,6 @@ SVG.Timeline = SVG.invent({
timeline: function () {
this._timeline = (this._timeline || new SVG.Timeline())
return this._timeline
- },
+ }
}
})
diff --git a/src/transform.js b/src/transform.js
index 6ea5269..96c0aec 100644
--- a/src/transform.js
+++ b/src/transform.js
@@ -1,4 +1,4 @@
-/* global arrayToMatrix getOrigin */
+/* global arrayToMatrix getOrigin isMatrixLike */
SVG.extend(SVG.Element, {
// Reset all transformations