aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/svg.js658
-rw-r--r--dist/svg.min.js4
-rw-r--r--gulpfile.js2
-rw-r--r--spec/spec/circle.js2
-rw-r--r--spec/spec/queue.js111
-rw-r--r--src/drawLoop.js82
-rw-r--r--src/ellipse.js4
-rw-r--r--src/fx.js1918
-rw-r--r--src/gradient.js3
-rw-r--r--src/matrix.js7
-rw-r--r--src/queue.js81
-rw-r--r--src/sugar.js302
-rw-r--r--src/timeline.js171
-rw-r--r--src/transform.js167
14 files changed, 2136 insertions, 1376 deletions
diff --git a/dist/svg.js b/dist/svg.js
index a66cf21..1c92b34 100644
--- a/dist/svg.js
+++ b/dist/svg.js
@@ -6,7 +6,7 @@
* @copyright Wout Fierens <wout@mick-wout.com>
* @license MIT
*
-* BUILT: Mon Mar 05 2018 02:39:10 GMT+1100 (AEDT)
+* BUILT: Tue Apr 17 2018 21:58:30 GMT+1000 (AEST)
*/;
(function(root, factory) {
@@ -282,6 +282,171 @@ SVG.defaults = {
}
}
+SVG.Queue = SVG.invent({
+ create: function () {
+ this._first = null
+ this._last = null
+ this.length = 0
+ this.id = 0
+ },
+
+ extend: {
+ push: function (value) {
+
+ // An item stores an id and the provided value
+ var item = { id: this.id++, value: value }
+
+ // Deal with the queue being empty or populated
+ if (this._last) {
+ this._last = this._last.next = item
+ } else {
+ this._last = this._first = item
+ }
+
+ this.length++
+ },
+
+ shift: function () {
+ if (this.length == 0) {
+ return
+ }
+
+ var remove = this._first
+ this._first = remove.next
+ this._last = --this.length ? this._last : null
+ return remove.value
+ },
+
+ // Shows us the first item in the list
+ first: function () {
+ return this._first && this._first.value
+ },
+
+ // Shows us the last item in the list
+ last: function () {
+ return this._last && this._last.value
+ },
+
+ // Removes the first item from the front where matcher returns true
+ remove: function (matcher) {
+ // Find the first match
+ var previous = null
+ var current = this._first
+ while (current) {
+
+ // If we have a match, we are done
+ if (matcher(current)) break
+
+ // Otherwise, advance both of the pointers
+ previous = current
+ current = current.next
+ }
+
+ // If we got the first item, adjust the first pointer
+ if (current && current === this._first)
+ this._first = this._first.next
+
+ // If we got the last item, adjust the last pointer
+ if (current && current === this._last)
+ this._last = previous
+
+ // If we got an item, fix the list and return the item
+ if (current) {
+ --this.length
+
+ if (previous) {
+ previous.next = current.next
+ }
+
+ return current.item
+ }
+ }
+ }
+})
+
+
+SVG.Draw = {
+ nextDraw: null,
+ frames: new SVG.Queue(),
+ timeouts: new SVG.Queue(),
+ frameCount: 0,
+ timeoutCount: 0,
+ timer: window.performance || window.Date,
+
+ frame: function (fn) {
+ SVG.Draw.frames.push({
+ id: SVG.Draw.frameCount,
+ run: fn
+ })
+
+ if (SVG.Draw.nextDraw === null) {
+ SVG.Draw.nextDraw = requestAnimationFrame(SVG.Draw._draw)
+ }
+
+ return ++SVG.Draw.frameCount
+ },
+
+ timeout: function (fn, delay) {
+ delay = delay || 0
+
+ // Work out when the event should fire
+ var time = SVG.Draw.timer.now() + delay
+
+ // Add the timeout to the end of the queue
+ var thisId = SVG.Draw.timeoutCount++
+ SVG.Draw.timeouts.push({
+ id: thisId,
+ run: fn,
+ time: time
+ })
+
+ // Request another animation frame if we need one
+ if (SVG.Draw.nextDraw === null) {
+ SVG.Draw.nextDraw = requestAnimationFrame(SVG.Draw._draw)
+ }
+
+ return thisId
+ },
+
+ cancelTimeout: function (id) {
+ // Find the index of the timeout to cancel and remove it
+ var index = SVG.Draw.timeouts.remove(function (t) { return t.id == id })
+ return index
+ },
+
+ _draw: function (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 tracking = true
+ var nextTimeout = null
+ var lastTimeout = SVG.Draw.timeouts.last()
+ while ((nextTimeout = SVG.Draw.timeouts.shift())) {
+ // Run the timeout if its time, or push it to the end
+ if (now > nextTimeout.time) {
+ nextTimeout.run()
+ } else {
+ SVG.Draw.timeouts.push(nextTimeout)
+ }
+
+ // If we hit the last item, we should stop shifting out more items
+ if (nextTimeout === lastTimeout) break
+ }
+
+ // Run all of the frames available up until this point
+ var lastFrame = SVG.Draw.frames.last()
+ var lastFrameId = SVG.Draw.frameCount
+ while (SVG.Draw.frames.first() && SVG.Draw.frames.first().id < lastFrameId) {
+ var nextFrame = SVG.Draw.frames.shift()
+ nextFrame.run(now)
+ }
+
+ // If we have remaining timeouts or frames, draw until we don't anymore
+ SVG.Draw.nextDraw = SVG.Draw.timeouts.length > 0 || SVG.Draw.frames.length > 0
+ ? requestAnimationFrame(SVG.Draw._draw)
+ : null
+ }
+}
+
/* globals fullHex, compToHex */
// Module for color convertions
@@ -1386,7 +1551,7 @@ SVG.Situation = SVG.invent({
})
-SVG.FX = SVG.invent({
+SVG.Timeline = SVG.invent({
create: function (element) {
this._target = element
@@ -2018,10 +2183,10 @@ SVG.FX = SVG.invent({
construct: {
// Get fx module or create a new one, then animate with given duration and ease
animate: function (o, ease, delay) {
- return (this.fx || (this.fx = new SVG.FX(this))).animate(o, ease, delay)
+ return (this.fx || (this.fx = new SVG.Timeline(this))).animate(o, ease, delay)
},
delay: function (delay) {
- return (this.fx || (this.fx = new SVG.FX(this))).delay(delay)
+ return (this.fx || (this.fx = new SVG.Timeline(this))).delay(delay)
},
stop: function (jumpToEnd, clearQueue) {
if (this.fx) {
@@ -2091,7 +2256,7 @@ SVG.MorphObj = SVG.invent({
})
-SVG.extend(SVG.FX, {
+SVG.extend(SVG.Timeline, {
// Add animatable attributes
attr: function (a, v, relative) {
// apply attributes individually
@@ -2266,6 +2431,13 @@ SVG.Matrix = SVG.invent({
// Transform a matrix into another matrix by manipulating the space
transform: function (o) {
+ // Check if o is a matrix and then left multiply it directly
+ if (o.a != null) {
+ var matrix = new SVG.Matrix(o)
+ var newMatrix = this.lmultiply(matrix)
+ return newMatrix
+ }
+
// Get all of the parameters required to form the matrix
var flipX = o.flip && (o.flip === 'x' || o.flip === 'both') ? -1 : 1
var flipY = o.flip && (o.flip === 'y' || o.flip === 'both') ? -1 : 1
@@ -2783,7 +2955,8 @@ SVG.extend(SVG.Element, {
SVG.extend(SVG.Element, {
// Add transformations
- transform: function (o, cyOrRel) {
+ transform: function (o, relative) {
+
// Get the bounding box of the element with no transformations applied
var bbox = this.bbox()
@@ -2792,20 +2965,6 @@ SVG.extend(SVG.Element, {
var decomposed = new SVG.Matrix(this).decompose()
return decomposed[o] || decomposed
- // Let the user pass in a matrix as well
- } else if (o.a != null) {
- // Construct a matrix from the first parameter
- var matrix = new SVG.Matrix(o)
-
- // If we have a relative matrix, we just apply the old matrix
- if (cyOrRel != null) {
- var oldMatrix = new SVG.Matrix(this)
- matrix = matrix.multiply(oldMatrix)
- }
-
- // Apply the matrix directly
- return this.attr('transform', matrix)
-
// Allow the user to define the origin with a string
} else if (typeof o.origin === 'string' ||
(o.origin == null && o.ox == null && o.oy == null)
@@ -2832,13 +2991,14 @@ SVG.extend(SVG.Element, {
}
// The user can pass a boolean, an SVG.Element or an SVG.Matrix or nothing
- var result = new SVG.Matrix(cyOrRel === true ? this : cyOrRel).transform(o)
+ var cleanRelative = relative === true ? this : (relative || false)
+ var result = new SVG.Matrix(cleanRelative).transform(o)
return this.attr('transform', result)
}
})
-SVG.extend(SVG.FX, {
- transform: function (o, relative) {
+SVG.extend(SVG.Timeline, {
+ transform: function (o, relative, affine) {
// // get target in case of the fx module, otherwise reference this
// var target = this.target()
@@ -2966,149 +3126,6 @@ SVG.extend(SVG.FX, {
}
})
-// TODO: DESTROY
-// =======
-//
-//
-// SVG.Transformation = SVG.invent({
-//
-// create: function(source, inversed){
-//
-// if(arguments.length > 1 && typeof inversed != 'boolean'){
-// return this.constructor.call(this, [].slice.call(arguments))
-// }
-//
-// if(Array.isArray(source)){
-// for(var i = 0, len = this.arguments.length; i < len; ++i){
-// this[this.arguments[i]] = source[i]
-// }
-// } else if(typeof source == 'object'){
-// for(var i = 0, len = this.arguments.length; i < len; ++i){
-// this[this.arguments[i]] = source[this.arguments[i]]
-// }
-// }
-//
-// this.inversed = false
-//
-// if(inversed === true){
-// this.inversed = true
-// }
-//
-// }
-//
-// , extend: {
-//
-// arguments: []
-// , method: ''
-//
-// , at: function(pos){
-//
-// var params = []
-//
-// for(var i = 0, len = this.arguments.length; i < len; ++i){
-// params.push(this[this.arguments[i]])
-// }
-//
-// var m = this._undo || new SVG.Matrix()
-//
-// m = new SVG.Matrix().morph(SVG.Matrix.prototype[this.method].apply(m, params)).at(pos)
-//
-// return this.inversed ? m.inverse() : m
-//
-// }
-//
-// , undo: function(o){
-// for(var i = 0, len = this.arguments.length; i < len; ++i){
-// o[this.arguments[i]] = typeof this[this.arguments[i]] == 'undefined' ? 0 : o[this.arguments[i]]
-// }
-//
-// // The method SVG.Matrix.extract which was used before calling this
-// // method to obtain a value for the parameter o doesn't return a cx and
-// // a cy so we use the ones that were provided to this object at its creation
-// o.cx = this.cx
-// o.cy = this.cy
-//
-// this._undo = new SVG[capitalize(this.method)](o, true).at(1)
-//
-// return this
-// }
-//
-// }
-//
-// })
-//
-// SVG.Translate = SVG.invent({
-//
-// parent: SVG.Matrix
-// , inherit: SVG.Transformation
-//
-// , create: function(source, inversed){
-// this.constructor.apply(this, [].slice.call(arguments))
-// }
-//
-// , extend: {
-// arguments: ['transformedX', 'transformedY']
-// , method: 'translate'
-// }
-//
-// })
-//
-// SVG.Rotate = SVG.invent({
-//
-// parent: SVG.Matrix
-// , inherit: SVG.Transformation
-//
-// , create: function(source, inversed){
-// this.constructor.apply(this, [].slice.call(arguments))
-// }
-//
-// , extend: {
-// arguments: ['rotation', 'cx', 'cy']
-// , method: 'rotate'
-// , at: function(pos){
-// var m = new SVG.Matrix().rotate(new SVG.Number().morph(this.rotation - (this._undo ? this._undo.rotation : 0)).at(pos), this.cx, this.cy)
-// return this.inversed ? m.inverse() : m
-// }
-// , undo: function(o){
-// this._undo = o
-// return this
-// }
-// }
-//
-// })
-//
-// SVG.Scale = SVG.invent({
-//
-// parent: SVG.Matrix
-// , inherit: SVG.Transformation
-//
-// , create: function(source, inversed){
-// this.constructor.apply(this, [].slice.call(arguments))
-// }
-//
-// , extend: {
-// arguments: ['scaleX', 'scaleY', 'cx', 'cy']
-// , method: 'scale'
-// }
-//
-// })
-//
-// SVG.Skew = SVG.invent({
-//
-// parent: SVG.Matrix
-// , inherit: SVG.Transformation
-//
-// , create: function(source, inversed){
-// this.constructor.apply(this, [].slice.call(arguments))
-// }
-//
-// , extend: {
-// arguments: ['skewX', 'skewY', 'cx', 'cy']
-// , method: 'skew'
-// }
-//
-// })
-
/* global camelCase */
SVG.extend(SVG.Element, {
@@ -3721,7 +3738,7 @@ SVG.Gradient = SVG.invent({
})
// Add animatable methods to both gradient and fx module
-SVG.extend([SVG.Gradient, SVG.FX], {
+SVG.extend([SVG.Gradient, SVG.Timeline], {
// From position
from: function (x, y) {
return (this._target || this).type === 'radialGradient'
@@ -3772,7 +3789,6 @@ SVG.Stop = SVG.invent({
return this
}
}
-
})
SVG.Pattern = SVG.invent({
@@ -4038,7 +4054,7 @@ SVG.Circle = SVG.invent({
}
})
-SVG.extend([SVG.Circle, SVG.FX], {
+SVG.extend([SVG.Circle, SVG.Timeline], {
// Radius x value
rx: function (rx) {
return this.attr('r', rx)
@@ -4065,7 +4081,7 @@ SVG.Ellipse = SVG.invent({
}
})
-SVG.extend([SVG.Ellipse, SVG.Rect, SVG.FX], {
+SVG.extend([SVG.Ellipse, SVG.Rect, SVG.Timeline], {
// Radius x value
rx: function (rx) {
return this.attr('rx', rx)
@@ -4820,157 +4836,157 @@ SVG.extend([SVG.Line, SVG.Polyline, SVG.Polygon, SVG.Path], {
}
})
-// Define list of available attributes for stroke and fill
-var sugar = {
- stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'],
- fill: ['color', 'opacity', 'rule'],
- prefix: function (t, a) {
- return a === 'color' ? t : t + '-' + a
- }
-}
-
-// Add sugar for fill and stroke
-;['fill', 'stroke'].forEach(function (m) {
- var extension = {}
- var i
-
- extension[m] = function (o) {
- if (typeof o === 'undefined') {
- return this
- }
- if (typeof o === 'string' || SVG.Color.isRgb(o) || (o && typeof o.fill === 'function')) {
- this.attr(m, o)
- } else {
- // set all attributes from sugar.fill and sugar.stroke list
- for (i = sugar[m].length - 1; i >= 0; i--) {
- if (o[sugar[m][i]] != null) {
- this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]])
- }
- }
- }
-
- return this
- }
-
- SVG.extend([SVG.Element, SVG.FX], extension)
-})
-
-SVG.extend([SVG.Element, SVG.FX], {
- // Let the user set the matrix directly
- matrix: function (mat, b, c, d, e, f) {
- // Act as a getter
- if (mat == null) {
- return new SVG.Matrix(this)
- }
-
- // Act as a setter, the user can pass a matrix or a set of numbers
- return this.attr('transform', new SVG.Matrix(mat, b, c, d, e, f))
- },
-
- // Map rotation to transform
- rotate: function (angle, cx, cy) {
- return this.transform({rotate: angle, ox: cx, oy: cy}, true)
- },
-
- // Map skew to transform
- skew: function (x, y, cx, cy) {
- return arguments.length === 1 || arguments.length === 3
- ? this.transform({skew: x, ox: y, oy: cx}, true)
- : this.transform({skew: [x, y], ox: cx, oy: cy}, true)
- },
-
- shear: function (lam, cx, cy) {
- return this.transform({shear: lam, ox: cx, oy: cy}, true)
- },
-
- // Map scale to transform
- scale: function (x, y, cx, cy) {
- return arguments.length === 1 || arguments.length === 3
- ? this.transform({ scale: x, ox: y, oy: cx }, true)
- : this.transform({ scale: [x, y], ox: cx, oy: cy }, true)
- },
-
- // Map translate to transform
- translate: function (x, y) {
- return this.transform({ translate: [x, y] }, true)
- },
-
- // Map relative translations to transform
- relative: function (x, y) {
- return this.transform({ relative: [x, y] }, true)
- },
-
- // Map flip to transform
- flip: function (direction, around) {
- var directionString = typeof direction === 'string' ? direction
- : isFinite(direction) ? 'both'
- : 'both'
- var origin = (direction === 'both' && isFinite(around)) ? [around, around]
- : (direction === 'x') ? [around, 0]
- : (direction === 'y') ? [0, around]
- : isFinite(direction) ? [direction, direction]
- : [0, 0]
- this.transform({flip: directionString, origin: origin}, true)
- },
-
- // Opacity
- opacity: function (value) {
- return this.attr('opacity', value)
- },
-
- // Relative move over x axis
- dx: function (x) {
- return this.x(new SVG.Number(x).plus(this instanceof SVG.FX ? 0 : this.x()), true)
- },
-
- // Relative move over y axis
- dy: function (y) {
- return this.y(new SVG.Number(y).plus(this instanceof SVG.FX ? 0 : this.y()), true)
- },
-
- // Relative move over x and y axes
- dmove: function (x, y) {
- return this.dx(x).dy(y)
- }
-})
-
-SVG.extend([SVG.Rect, SVG.Ellipse, SVG.Circle, SVG.Gradient, SVG.FX], {
- // Add x and y radius
- radius: function (x, y) {
- var type = (this._target || this).type
- return type === 'radialGradient' || type === 'radialGradient'
- ? this.attr('r', new SVG.Number(x))
- : this.rx(x).ry(y == null ? x : y)
- }
-})
-
-SVG.extend(SVG.Path, {
- // Get path length
- length: function () {
- return this.node.getTotalLength()
- },
- // Get point at length
- pointAt: function (length) {
- return new SVG.Point(this.node.getPointAtLength(length))
- }
-})
-
-SVG.extend([SVG.Parent, SVG.Text, SVG.Tspan, SVG.FX], {
- // Set font
- font: function (a, v) {
- if (typeof a === 'object') {
- for (v in a) this.font(v, a[v])
- }
-
- return a === 'leading'
- ? this.leading(v)
- : a === 'anchor'
- ? this.attr('text-anchor', v)
- : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style'
- ? this.attr('font-' + a, v)
- : this.attr(a, v)
- }
-})
+// // Define list of available attributes for stroke and fill
+// var sugar = {
+// stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'],
+// fill: ['color', 'opacity', 'rule'],
+// prefix: function (t, a) {
+// return a === 'color' ? t : t + '-' + a
+// }
+// }
+//
+// // Add sugar for fill and stroke
+// ;['fill', 'stroke'].forEach(function (m) {
+// var extension = {}
+// var i
+//
+// extension[m] = function (o) {
+// if (typeof o === 'undefined') {
+// return this
+// }
+// if (typeof o === 'string' || SVG.Color.isRgb(o) || (o && typeof o.fill === 'function')) {
+// this.attr(m, o)
+// } else {
+// // set all attributes from sugar.fill and sugar.stroke list
+// for (i = sugar[m].length - 1; i >= 0; i--) {
+// if (o[sugar[m][i]] != null) {
+// this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]])
+// }
+// }
+// }
+//
+// return this
+// }
+//
+// SVG.extend([SVG.Element, SVG.Timeline], extension)
+// })
+//
+// SVG.extend([SVG.Element, SVG.Timeline], {
+// // Let the user set the matrix directly
+// matrix: function (mat, b, c, d, e, f) {
+// // Act as a getter
+// if (mat == null) {
+// return new SVG.Matrix(this)
+// }
+//
+// // Act as a setter, the user can pass a matrix or a set of numbers
+// return this.attr('transform', new SVG.Matrix(mat, b, c, d, e, f))
+// },
+//
+// // Map rotation to transform
+// rotate: function (angle, cx, cy) {
+// return this.transform({rotate: angle, ox: cx, oy: cy}, true)
+// },
+//
+// // Map skew to transform
+// skew: function (x, y, cx, cy) {
+// return arguments.length === 1 || arguments.length === 3
+// ? this.transform({skew: x, ox: y, oy: cx}, true)
+// : this.transform({skew: [x, y], ox: cx, oy: cy}, true)
+// },
+//
+// shear: function (lam, cx, cy) {
+// return this.transform({shear: lam, ox: cx, oy: cy}, true)
+// },
+//
+// // Map scale to transform
+// scale: function (x, y, cx, cy) {
+// return arguments.length === 1 || arguments.length === 3
+// ? this.transform({ scale: x, ox: y, oy: cx }, true)
+// : this.transform({ scale: [x, y], ox: cx, oy: cy }, true)
+// },
+//
+// // Map translate to transform
+// translate: function (x, y) {
+// return this.transform({ translate: [x, y] }, true)
+// },
+//
+// // Map relative translations to transform
+// relative: function (x, y) {
+// return this.transform({ relative: [x, y] }, true)
+// },
+//
+// // Map flip to transform
+// flip: function (direction, around) {
+// var directionString = typeof direction === 'string' ? direction
+// : isFinite(direction) ? 'both'
+// : 'both'
+// var origin = (direction === 'both' && isFinite(around)) ? [around, around]
+// : (direction === 'x') ? [around, 0]
+// : (direction === 'y') ? [0, around]
+// : isFinite(direction) ? [direction, direction]
+// : [0, 0]
+// this.transform({flip: directionString, origin: origin}, true)
+// },
+//
+// // Opacity
+// opacity: function (value) {
+// return this.attr('opacity', value)
+// },
+//
+// // Relative move over x axis
+// dx: function (x) {
+// return this.x(new SVG.Number(x).plus(this instanceof SVG.Timeline ? 0 : this.x()), true)
+// },
+//
+// // Relative move over y axis
+// dy: function (y) {
+// return this.y(new SVG.Number(y).plus(this instanceof SVG.Timeline ? 0 : this.y()), true)
+// },
+//
+// // Relative move over x and y axes
+// dmove: function (x, y) {
+// return this.dx(x).dy(y)
+// }
+// })
+//
+// SVG.extend([SVG.Rect, SVG.Ellipse, SVG.Circle, SVG.Gradient, SVG.Timeline], {
+// // Add x and y radius
+// radius: function (x, y) {
+// var type = (this._target || this).type
+// return type === 'radialGradient' || type === 'radialGradient'
+// ? this.attr('r', new SVG.Number(x))
+// : this.rx(x).ry(y == null ? x : y)
+// }
+// })
+//
+// SVG.extend(SVG.Path, {
+// // Get path length
+// length: function () {
+// return this.node.getTotalLength()
+// },
+// // Get point at length
+// pointAt: function (length) {
+// return new SVG.Point(this.node.getPointAtLength(length))
+// }
+// })
+//
+// SVG.extend([SVG.Parent, SVG.Text, SVG.Tspan, SVG.Timeline], {
+// // Set font
+// font: function (a, v) {
+// if (typeof a === 'object') {
+// for (v in a) this.font(v, a[v])
+// }
+//
+// return a === 'leading'
+// ? this.leading(v)
+// : a === 'anchor'
+// ? this.attr('text-anchor', v)
+// : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style'
+// ? this.attr('font-' + a, v)
+// : this.attr(a, v)
+// }
+// })
SVG.extend(SVG.Element, {
diff --git a/dist/svg.min.js b/dist/svg.min.js
index 0919e6c..c589c44 100644
--- a/dist/svg.min.js
+++ b/dist/svg.min.js
@@ -1,2 +1,2 @@
-/*! svg.js v3.0.0 MIT*/;!function(t,e){"function"==typeof define&&define.amd?define(function(){return e(t,t.document)}):"object"==typeof exports?module.exports=t.document?e(t,t.document):function(t){return e(t,t.document)}:t.SVG=e(t,t.document)}("undefined"!=typeof window?window:this,function(t,e){function n(t,n){if(t instanceof w.Element)return t;if("object"==typeof t)return w.adopt(t);if(null==t)return new w.Doc;if("string"==typeof t&&"<"!==t.charAt(0))return w.adopt(e.querySelector(t));var i=w.create("svg");return i.innerHTML=t,t=w.adopt(i.firstElementChild)}function i(t){return!(t.w||t.h||t.x||t.y)}function r(t){return(e.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t===e}).call(e.documentElement,t)}function s(t,e,n,i){return n+i.replace(w.regex.dots," .")}function o(t){for(var e=t.slice(0),n=e.length;n--;)Array.isArray(e[n])&&(e[n]=o(e[n]));return e}function a(t,e){return t instanceof e}function h(t,e){return(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)}function u(t){return t.toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()})}function l(t){return t.charAt(0).toUpperCase()+t.slice(1)}function c(t){return 4===t.length?["#",t.substring(1,2),t.substring(1,2),t.substring(2,3),t.substring(2,3),t.substring(3,4),t.substring(3,4)].join(""):t}function f(t){var e=t.toString(16);return 1===e.length?"0"+e:e}function d(t,e,n){if(null==e||null==n){var i=t.bbox();null==e?e=i.width/i.height*n:null==n&&(n=i.height/i.width*e)}return{width:e,height:n}}function p(t){return{a:t[0],b:t[1],c:t[2],d:t[3],e:t[4],f:t[5]}}function m(t){for(var e=0,n=t.length,i="";e<n;e++)i+=t[e][0],null!=t[e][1]&&(i+=t[e][1],null!=t[e][2]&&(i+=" ",i+=t[e][2],null!=t[e][3]&&(i+=" ",i+=t[e][3],i+=" ",i+=t[e][4],null!=t[e][5]&&(i+=" ",i+=t[e][5],i+=" ",i+=t[e][6],null!=t[e][7]&&(i+=" ",i+=t[e][7])))));return i+" "}function x(t){for(var e=t.children.length-1;e>=0;e--)x(t.children[e]);return t.id?w.adopt(t).id(w.eid(t.nodeName)):w.adopt(t)}function v(t){return null==t.x&&(t.x=0,t.y=0,t.width=0,t.height=0),t.w=t.width,t.h=t.height,t.x2=t.x+t.width,t.y2=t.y+t.height,t.cx=t.x+t.width/2,t.cy=t.y+t.height/2,t}function y(t){var e=(t||"").toString().match(w.regex.reference);if(e)return e[1]}function g(t,e,n){return Math.abs(e-t)<(n||1e-6)}if(!e.createElementNS||!e.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect)return{supported:!1};var w=this.SVG=function(t){if(w.supported)return t=n(t)};w.supported=!0,w.ns="http://www.w3.org/2000/svg",w.xmlns="http://www.w3.org/2000/xmlns/",w.xlink="http://www.w3.org/1999/xlink",w.svgjs="http://svgjs.com/svgjs",w.did=1e3,w.eid=function(t){return"Svgjs"+l(t)+w.did++},w.create=function(t){return e.createElementNS(this.ns,t)},w.extend=function(t,e){var n,i;for(t=Array.isArray(t)?t:[t],i=t.length-1;i>=0;i--)if(t[i])for(n in e)t[i].prototype[n]=e[n]},w.invent=function(t){var e="function"==typeof t.create?t.create:function(e){this.constructor(e||w.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&w.extend(e,t.extend),t.construct&&w.extend(t.parent||w.Container,t.construct),e},w.adopt=function(e){if(!e)return null;if(e.instance instanceof w.Element)return e.instance;if(!(e instanceof t.SVGElement))return new w.HtmlNode(e);return"svg"===e.nodeName?new w.Doc(e):"linearGradient"===e.nodeName||"radialGradient"===e.nodeName?new w.Gradient(e):w[l(e.nodeName)]?new(w[l(e.nodeName)])(e):new w.Parent(e)},w.regex={numberAndUnit:/^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+)\)/,reference:/#([a-z0-9\-_]+)/i,transforms:/\)\s*,?\s*/,whitespace:/\s/g,isHex:/^#[a-f0-9]{3,6}$/i,isRgb:/^rgb\(/,isCss:/[^:]+:[^;]+;?/,isBlank:/^(\s+)?$/,isNumber:/^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,isPercent:/^-?[\d.]+%$/,isImage:/\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,delimiter:/[\s,]+/,hyphen:/([^e])-/gi,pathLetters:/[MLHVCSQTAZ]/gi,isPathLetter:/[MLHVCSQTAZ]/i,numbersWithDots:/((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi,dots:/\./g},w.utils={map:function(t,e){var n,i=t.length,r=[];for(n=0;n<i;n++)r.push(e(t[n]));return r},filter:function(t,e){var n,i=t.length,r=[];for(n=0;n<i;n++)e(t[n])&&r.push(t[n]);return r},radians:function(t){return t%360*Math.PI/180},degrees:function(t){return 180*t/Math.PI%360},filterSVGElements:function(e){return this.filter(e,function(e){return e instanceof t.SVGElement})}},w.defaults={attrs:{"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"}},w.Color=function(t){var e;this.r=0,this.g=0,this.b=0,t&&("string"==typeof t?w.regex.isRgb.test(t)?(e=w.regex.rgb.exec(t.replace(w.regex.whitespace,"")),this.r=parseInt(e[1]),this.g=parseInt(e[2]),this.b=parseInt(e[3])):w.regex.isHex.test(t)&&(e=w.regex.hex.exec(c(t)),this.r=parseInt(e[1],16),this.g=parseInt(e[2],16),this.b=parseInt(e[3],16)):"object"==typeof t&&(this.r=t.r,this.g=t.g,this.b=t.b))},w.extend(w.Color,{toString:function(){return this.toHex()},toHex:function(){return"#"+f(this.r)+f(this.g)+f(this.b)},toRgb:function(){return"rgb("+[this.r,this.g,this.b].join()+")"},brightness:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11},morph:function(t){return this.destination=new w.Color(t),this},at:function(t){return this.destination?(t=t<0?0:t>1?1:t,new w.Color({r:~~(this.r+(this.destination.r-this.r)*t),g:~~(this.g+(this.destination.g-this.g)*t),b:~~(this.b+(this.destination.b-this.b)*t)})):this}}),w.Color.test=function(t){return t+="",w.regex.isHex.test(t)||w.regex.isRgb.test(t)},w.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},w.Color.isColor=function(t){return w.Color.isRgb(t)||w.Color.test(t)},w.Array=function(t,e){t=(t||[]).valueOf(),0===t.length&&e&&(t=e.valueOf()),this.value=this.parse(t)},w.extend(w.Array,{morph:function(t){if(this.destination=this.parse(t),this.value.length!==this.destination.length){for(var e=this.value[this.value.length-1],n=this.destination[this.destination.length-1];this.value.length>this.destination.length;)this.destination.push(n);for(;this.value.length<this.destination.length;)this.value.push(e)}return this},settle:function(){for(var t=0,e=this.value.length,n=[];t<e;t++)-1===n.indexOf(this.value[t])&&n.push(this.value[t]);return this.value=n,n},at:function(t){if(!this.destination)return this;for(var e=0,n=this.value.length,i=[];e<n;e++)i.push(this.value[e]+(this.destination[e]-this.value[e])*t);return new w.Array(i)},toString:function(){return this.value.join(" ")},valueOf:function(){return this.value},parse:function(t){return t=t.valueOf(),Array.isArray(t)?t:t.trim().split(w.regex.delimiter).map(parseFloat)},reverse:function(){return this.value.reverse(),this},clone:function(){var t=new this.constructor;return t.value=o(this.value),t}}),w.PointArray=function(t,e){w.Array.call(this,t,e||[[0,0]])},w.PointArray.prototype=new w.Array,w.PointArray.prototype.constructor=w.PointArray,w.extend(w.PointArray,{toString:function(){for(var t=0,e=this.value.length,n=[];t<e;t++)n.push(this.value[t].join(","));return n.join(" ")},toLine:function(){return{x1:this.value[0][0],y1:this.value[0][1],x2:this.value[1][0],y2:this.value[1][1]}},at:function(t){if(!this.destination)return this;for(var e=0,n=this.value.length,i=[];e<n;e++)i.push([this.value[e][0]+(this.destination[e][0]-this.value[e][0])*t,this.value[e][1]+(this.destination[e][1]-this.value[e][1])*t]);return new w.PointArray(i)},parse:function(t){var e=[];if(t=t.valueOf(),Array.isArray(t)){if(Array.isArray(t[0]))return t}else t=t.trim().split(w.regex.delimiter).map(parseFloat);t.length%2!=0&&t.pop();for(var n=0,i=t.length;n<i;n+=2)e.push([t[n],t[n+1]]);return e},move:function(t,e){var n=this.bbox();if(t-=n.x,e-=n.y,!isNaN(t)&&!isNaN(e))for(var i=this.value.length-1;i>=0;i--)this.value[i]=[this.value[i][0]+t,this.value[i][1]+e];return this},size:function(t,e){var n,i=this.bbox();for(n=this.value.length-1;n>=0;n--)i.width&&(this.value[n][0]=(this.value[n][0]-i.x)*t/i.width+i.x),i.height&&(this.value[n][1]=(this.value[n][1]-i.y)*e/i.height+i.y);return this},bbox:function(){var t=-1/0,e=-1/0,n=1/0,i=1/0;return this.value.forEach(function(r){t=Math.max(r[0],t),e=Math.max(r[1],e),n=Math.min(r[0],n),i=Math.min(r[1],i)}),{x:n,y:i,width:t-n,height:e-i}}});for(var b={M:function(t,e,n){return e.x=n.x=t[0],e.y=n.y=t[1],["M",e.x,e.y]},L:function(t,e){return e.x=t[0],e.y=t[1],["L",t[0],t[1]]},H:function(t,e){return e.x=t[0],["H",t[0]]},V:function(t,e){return e.y=t[0],["V",t[0]]},C:function(t,e){return e.x=t[4],e.y=t[5],["C",t[0],t[1],t[2],t[3],t[4],t[5]]},S:function(t,e){return e.x=t[2],e.y=t[3],["S",t[0],t[1],t[2],t[3]]},Q:function(t,e){return e.x=t[2],e.y=t[3],["Q",t[0],t[1],t[2],t[3]]},T:function(t,e){return e.x=t[0],e.y=t[1],["T",t[0],t[1]]},Z:function(t,e,n){return e.x=n.x,e.y=n.y,["Z"]},A:function(t,e){return e.x=t[5],e.y=t[6],["A",t[0],t[1],t[2],t[3],t[4],t[5],t[6]]}},P="mlhvqtcsaz".split(""),A=0,C=P.length;A<C;++A)b[P[A]]=function(t){return function(e,n,i){if("H"===t)e[0]=e[0]+n.x;else if("V"===t)e[0]=e[0]+n.y;else if("A"===t)e[5]=e[5]+n.x,e[6]=e[6]+n.y;else for(var r=0,s=e.length;r<s;++r)e[r]=e[r]+(r%2?n.y:n.x);return b[t](e,n,i)}}(P[A].toUpperCase());w.PathArray=function(t,e){w.Array.call(this,t,e||[["M",0,0]])},w.PathArray.prototype=new w.Array,w.PathArray.prototype.constructor=w.PathArray,w.extend(w.PathArray,{toString:function(){return m(this.value)},move:function(t,e){var n=this.bbox();if(t-=n.x,e-=n.y,!isNaN(t)&&!isNaN(e))for(var i,r=this.value.length-1;r>=0;r--)i=this.value[r][0],"M"===i||"L"===i||"T"===i?(this.value[r][1]+=t,this.value[r][2]+=e):"H"===i?this.value[r][1]+=t:"V"===i?this.value[r][1]+=e:"C"===i||"S"===i||"Q"===i?(this.value[r][1]+=t,this.value[r][2]+=e,this.value[r][3]+=t,this.value[r][4]+=e,"C"===i&&(this.value[r][5]+=t,this.value[r][6]+=e)):"A"===i&&(this.value[r][6]+=t,this.value[r][7]+=e);return this},size:function(t,e){var n,i,r=this.bbox();for(n=this.value.length-1;n>=0;n--)i=this.value[n][0],"M"===i||"L"===i||"T"===i?(this.value[n][1]=(this.value[n][1]-r.x)*t/r.width+r.x,this.value[n][2]=(this.value[n][2]-r.y)*e/r.height+r.y):"H"===i?this.value[n][1]=(this.value[n][1]-r.x)*t/r.width+r.x:"V"===i?this.value[n][1]=(this.value[n][1]-r.y)*e/r.height+r.y:"C"===i||"S"===i||"Q"===i?(this.value[n][1]=(this.value[n][1]-r.x)*t/r.width+r.x,this.value[n][2]=(this.value[n][2]-r.y)*e/r.height+r.y,this.value[n][3]=(this.value[n][3]-r.x)*t/r.width+r.x,this.value[n][4]=(this.value[n][4]-r.y)*e/r.height+r.y,"C"===i&&(this.value[n][5]=(this.value[n][5]-r.x)*t/r.width+r.x,this.value[n][6]=(this.value[n][6]-r.y)*e/r.height+r.y)):"A"===i&&(this.value[n][1]=this.value[n][1]*t/r.width,this.value[n][2]=this.value[n][2]*e/r.height,this.value[n][6]=(this.value[n][6]-r.x)*t/r.width+r.x,this.value[n][7]=(this.value[n][7]-r.y)*e/r.height+r.y);return this},equalCommands:function(t){var e,n,i;for(t=new w.PathArray(t),i=this.value.length===t.value.length,e=0,n=this.value.length;i&&e<n;e++)i=this.value[e][0]===t.value[e][0];return i},morph:function(t){return t=new w.PathArray(t),this.equalCommands(t)?this.destination=t:this.destination=null,this},at:function(t){if(!this.destination)return this;var e,n,i,r,s=this.value,o=this.destination.value,a=[],h=new w.PathArray;for(e=0,n=s.length;e<n;e++){for(a[e]=[s[e][0]],i=1,r=s[e].length;i<r;i++)a[e][i]=s[e][i]+(o[e][i]-s[e][i])*t;"A"===a[e][0]&&(a[e][4]=+(0!==a[e][4]),a[e][5]=+(0!==a[e][5]))}return h.value=a,h},parse:function(t){if(t instanceof w.PathArray)return t.valueOf();var e,n={M:2,L:2,H:1,V:1,C:6,S:4,Q:4,T:2,A:7,Z:0};t="string"==typeof t?t.replace(w.regex.numbersWithDots,s).replace(w.regex.pathLetters," $& ").replace(w.regex.hyphen,"$1 -").trim().split(w.regex.delimiter):t.reduce(function(t,e){return[].concat.call(t,e)},[]);var i=[],r=new w.Point,o=new w.Point,a=0,h=t.length;do{w.regex.isPathLetter.test(t[a])?(e=t[a],++a):"M"===e?e="L":"m"===e&&(e="l"),i.push(b[e].call(null,t.slice(a,a+=n[e.toUpperCase()]).map(parseFloat),r,o))}while(h>a);return i},bbox:function(){return w.parser().path.setAttribute("d",this.toString()),w.parser.nodes.path.getBBox()}}),w.Number=w.invent({create:function(t,e){this.value=0,this.unit=e||"","number"==typeof t?this.value=isNaN(t)?0:isFinite(t)?t:t<0?-3.4e38:3.4e38:"string"==typeof t?(e=t.match(w.regex.numberAndUnit))&&(this.value=parseFloat(e[1]),"%"===e[5]?this.value/=100:"s"===e[5]&&(this.value*=1e3),this.unit=e[5]):t instanceof w.Number&&(this.value=t.valueOf(),this.unit=t.unit)},extend:{toString:function(){return("%"===this.unit?~~(1e8*this.value)/1e6:"s"===this.unit?this.value/1e3:this.value)+this.unit},toJSON:function(){return this.toString()},valueOf:function(){return this.value},plus:function(t){return t=new w.Number(t),new w.Number(this+t,this.unit||t.unit)},minus:function(t){return t=new w.Number(t),new w.Number(this-t,this.unit||t.unit)},times:function(t){return t=new w.Number(t),new w.Number(this*t,this.unit||t.unit)},divide:function(t){return t=new w.Number(t),new w.Number(this/t,this.unit||t.unit)},to:function(t){var e=new w.Number(this);return"string"==typeof t&&(e.unit=t),e},morph:function(t){return this.destination=new w.Number(t),t.relative&&(this.destination.value+=this.value),this},at:function(t){return this.destination?new w.Number(this.destination).minus(this).times(t).plus(this):this}}}),w.HtmlNode=w.invent({create:function(t){this.node=t},extend:{add:function(t,e){return t=n(t),t.node!==this.node.children[e]&&this.node.insertBefore(t.node,this.node.children[e]||null),this},put:function(t,e){return this.add(t,e),t}}}),w.Element=w.invent({create:function(t){this.events={},this.dom={},this.node=t,this.node&&(this.type=t.nodeName,this.node.instance=this,this.events=t.events||{},t.hasAttribute("svgjs:data")&&this.setData(JSON.parse(t.getAttribute("svgjs:data"))||{}))},extend:{x:function(t){return this.attr("x",t)},y:function(t){return this.attr("y",t)},cx:function(t){return null==t?this.x()+this.width()/2:this.x(t-this.width()/2)},cy:function(t){return null==t?this.y()+this.height()/2:this.y(t-this.height()/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},width:function(t){return this.attr("width",t)},height:function(t){return this.attr("height",t)},size:function(t,e){var n=d(this,t,e);return this.width(new w.Number(n.width)).height(new w.Number(n.height))},clone:function(t){this.writeDataToDom();var e=x(this.node.cloneNode(!0));return t?t.add(e):this.after(e),e},remove:function(){return this.parent()&&this.parent().removeElement(this),this},replace:function(t){return this.after(t).remove(),t},addTo:function(t){return n(t).put(this)},putIn:function(t){return n(t).add(this)},id:function(t){return void 0!==t||this.node.id||(this.node.id=w.eid(this.type)),this.attr("id",t)},inside:function(t,e){var n=this.bbox();return t>n.x&&e>n.y&&t<n.x+n.width&&e<n.y+n.height},show:function(){return this.css("display","")},hide:function(){return this.css("display","none")},visible:function(){return"none"!==this.css("display")},toString:function(){return this.id()},classes:function(){var t=this.attr("class");return null==t?[]:t.trim().split(w.regex.delimiter)},hasClass:function(t){return-1!==this.classes().indexOf(t)},addClass:function(t){if(!this.hasClass(t)){var e=this.classes();e.push(t),this.attr("class",e.join(" "))}return this},removeClass:function(t){return this.hasClass(t)&&this.attr("class",this.classes().filter(function(e){return e!==t}).join(" ")),this},toggleClass:function(t){return this.hasClass(t)?this.removeClass(t):this.addClass(t)},reference:function(t){return w.get(this.attr(t))},parent:function(e){var n=this;if(!n.node.parentNode)return null;if(n=w.adopt(n.node.parentNode),!e)return n;for(;n&&n.node instanceof t.SVGElement;){if("string"==typeof e?n.matches(e):n instanceof e)return n;n=w.adopt(n.node.parentNode)}},doc:function(){var t=this.parent(w.Doc);return t&&t.doc()},defs:function(){return this.doc().defs()},parents:function(t){var e=[],n=this;do{if(!(n=n.parent(t))||!n.node)break;e.push(n)}while(n.parent);return e},matches:function(t){return h(this.node,t)},native:function(){return this.node},svg:function(t){var n,i;if(!(t&&this instanceof w.Parent))return this.writeDataToDom(),this.node.outerHTML;for(n=e.createElementNS(w.ns,"svg"),n.innerHTML=t,i=n.children.length;i--;)this.node.appendChild(n.firstElementChild);return this},writeDataToDom:function(){return this.is(w.Parent)&&this.each(function(){this.writeDataToDom()}),this.node.removeAttribute("svgjs:data"),Object.keys(this.dom).length&&this.node.setAttribute("svgjs:data",JSON.stringify(this.dom)),this},setData:function(t){return this.dom=t,this},is:function(t){return a(this,t)}}}),w.easing={"-":function(t){return t},"<>":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)}},w.morph=function(t){return function(e,n){return new w.MorphObj(e,n).at(t)}},w.Situation=w.invent({create:function(t){this.init=!1,this.reversed=!1,this.reversing=!1,this.duration=new w.Number(t.duration).valueOf(),this.delay=new w.Number(t.delay).valueOf(),this.start=+new Date+this.delay,this.finish=this.start+this.duration,this.ease=t.ease,this.loop=0,this.loops=!1,this.animations={},this.attrs={},this.styles={},this.transforms=[],this.once={}}}),w.FX=w.invent({create:function(t){this._target=t,this.situations=[],this.active=!1,this.situation=null,this.paused=!1,this.lastPos=0,this.pos=0,this.absPos=0,this._speed=1},extend:{animate:function(t,e,n){"object"==typeof t&&(e=t.ease,n=t.delay,t=t.duration);var i=new w.Situation({duration:t||1e3,delay:n||0,ease:w.easing[e||"-"]||e});return this.queue(i),this},delay:function(t){var e=new w.Situation({duration:t,delay:0,ease:w.easing["-"]});return this.queue(e)},target:function(t){return t&&t instanceof w.Element?(this._target=t,this):this._target},timeToAbsPos:function(t){return(t-this.situation.start)/(this.situation.duration/this._speed)},absPosToTime:function(t){return this.situation.duration/this._speed*t+this.situation.start},startAnimFrame:function(){this.stopAnimFrame(),this.animationFrame=t.requestAnimationFrame(function(){this.step()}.bind(this))},stopAnimFrame:function(){t.cancelAnimationFrame(this.animationFrame)},start:function(){return!this.active&&this.situation&&(this.active=!0,this.startCurrent()),this},startCurrent:function(){return this.situation.start=+new Date+this.situation.delay/this._speed,this.situation.finish=this.situation.start+this.situation.duration/this._speed,this.initAnimations().step()},queue:function(t){return("function"==typeof t||t instanceof w.Situation)&&this.situations.push(t),this.situation||(this.situation=this.situations.shift()),this},dequeue:function(){return this.stop(),this.situation=this.situations.shift(),this.situation&&(this.situation instanceof w.Situation?this.start():this.situation(this)),this},initAnimations:function(){var t,e,n,i=this.situation;if(i.init)return this;for(t in i.animations)for(n=this.target()[t](),Array.isArray(n)||(n=[n]),Array.isArray(i.animations[t])||(i.animations[t]=[i.animations[t]]),e=n.length;e--;)i.animations[t][e]instanceof w.Number&&(n[e]=new w.Number(n[e])),i.animations[t][e]=n[e].morph(i.animations[t][e]);for(t in i.attrs)i.attrs[t]=new w.MorphObj(this.target().attr(t),i.attrs[t]);for(t in i.styles)i.styles[t]=new w.MorphObj(this.target().css(t),i.styles[t]);return i.initialTransformation=this.target().matrixify(),i.init=!0,this},clearQueue:function(){return this.situations=[],this},clearCurrent:function(){return this.situation=null,this},stop:function(t,e){var n=this.active;return this.active=!1,e&&this.clearQueue(),t&&this.situation&&(!n&&this.startCurrent(),this.atEnd()),this.stopAnimFrame(),this.clearCurrent()},reset:function(){if(this.situation){var t=this.situation;this.stop(),this.situation=t,this.atStart()}return this},finish:function(){for(this.stop(!0,!1);this.dequeue().situation&&this.stop(!0,!1););return this.clearQueue().clearCurrent(),this},atStart:function(){return this.at(0,!0)},atEnd:function(){return!0===this.situation.loops&&(this.situation.loops=this.situation.loop+1),"number"==typeof this.situation.loops?this.at(this.situation.loops,!0):this.at(1,!0)},at:function(t,e){var n=this.situation.duration/this._speed;return this.absPos=t,e||(this.situation.reversed&&(this.absPos=1-this.absPos),this.absPos+=this.situation.loop),this.situation.start=+new Date-this.absPos*n,this.situation.finish=this.situation.start+n,this.step(!0)},speed:function(t){return 0===t?this.pause():t?(this._speed=t,this.at(this.absPos,!0)):this._speed},loop:function(t,e){var n=this.last();return n.loops=null==t||t,n.loop=0,e&&(n.reversing=!0),this},pause:function(){return this.paused=!0,this.stopAnimFrame(),this},play:function(){return this.paused?(this.paused=!1,this.at(this.absPos,!0)):this},reverse:function(t){var e=this.last();return e.reversed=void 0===t?!e.reversed:t,this},progress:function(t){return t?this.situation.ease(this.pos):this.pos},after:function(t){function e(i){i.detail.situation===n&&(t.call(this,n),this.off("finished.fx",e))}var n=this.last();return this.target().on("finished.fx",e),this._callStart()},during:function(t){function e(e){e.detail.situation===n&&t.call(this,e.detail.pos,w.morph(e.detail.pos),e.detail.eased,n)}var n=this.last();return this.target().off("during.fx",e).on("during.fx",e),this.after(function(){this.off("during.fx",e)}),this._callStart()},afterAll:function(t){var e=function e(n){t.call(this),this.off("allfinished.fx",e)};return this.target().off("allfinished.fx",e).on("allfinished.fx",e),this._callStart()},duringAll:function(t){var e=function(e){t.call(this,e.detail.pos,w.morph(e.detail.pos),e.detail.eased,e.detail.situation)};return this.target().off("during.fx",e).on("during.fx",e),this.afterAll(function(){this.off("during.fx",e)}),this._callStart()},last:function(){return this.situations.length?this.situations[this.situations.length-1]:this.situation},add:function(t,e,n){return this.last()[n||"animations"][t]=e,this._callStart()},step:function(t){if(t||(this.absPos=this.timeToAbsPos(+new Date)),!1!==this.situation.loops){var e,n,i;e=Math.max(this.absPos,0),n=Math.floor(e),!0===this.situation.loops||n<this.situation.loops?(this.pos=e-n,i=this.situation.loop,this.situation.loop=n):(this.absPos=this.situation.loops,this.pos=1,i=this.situation.loop-1,this.situation.loop=this.situation.loops),this.situation.reversing&&(this.situation.reversed=this.situation.reversed!==Boolean((this.situation.loop-i)%2))}else this.absPos=Math.min(this.absPos,1),this.pos=this.absPos;this.pos<0&&(this.pos=0),this.situation.reversed&&(this.pos=1-this.pos);var r=this.situation.ease(this.pos);for(var s in this.situation.once)s>this.lastPos&&s<=r&&(this.situation.once[s].call(this.target(),this.pos,r),delete this.situation.once[s]);return this.active&&this.target().fire("during",{pos:this.pos,eased:r,fx:this,situation:this.situation}),this.situation?(this.eachAt(),1===this.pos&&!this.situation.reversed||this.situation.reversed&&0===this.pos?(this.stopAnimFrame(),this.target().fire("finished",{fx:this,situation:this.situation}),this.situations.length||(this.target().fire("allfinished"),this.situations.length||(this.target().off(".fx"),this.active=!1)),this.active?this.dequeue():this.clearCurrent()):!this.paused&&this.active&&this.startAnimFrame(),this.lastPos=r,this):this},eachAt:function(){var t,e,n=this,i=this.target(),r=this.situation;for(t in r.animations)e=[].concat(r.animations[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(n.pos),n.pos):t}),i[t].apply(i,e);for(t in r.attrs)e=[t].concat(r.attrs[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(n.pos),n.pos):t}),i.attr.apply(i,e);for(t in r.styles)e=[t].concat(r.styles[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(n.pos),n.pos):t}),i.css.apply(i,e);return r.transforms.length,this},once:function(t,e,n){var i=this.last();return n||(t=i.ease(t)),i.once[t]=e,this},_callStart:function(){return setTimeout(function(){this.start()}.bind(this),0),this}},parent:w.Element,construct:{animate:function(t,e,n){return(this.fx||(this.fx=new w.FX(this))).animate(t,e,n)},delay:function(t){return(this.fx||(this.fx=new w.FX(this))).delay(t)},stop:function(t,e){return this.fx&&this.fx.stop(t,e),this},finish:function(){return this.fx&&this.fx.finish(),this},pause:function(){return this.fx&&this.fx.pause(),this},play:function(){return this.fx&&this.fx.play(),this},speed:function(t){if(this.fx){if(null==t)return this.fx.speed();this.fx.speed(t)}return this}}}),w.MorphObj=w.invent({create:function(t,e){return w.Color.isColor(e)?new w.Color(t).morph(e):w.regex.delimiter.test(t)?new w.Array(t).morph(e):w.regex.numberAndUnit.test(e)?new w.Number(t).morph(e):(this.value=t,void(this.destination=e))},extend:{at:function(t,e){return e<1?this.value:this.destination},valueOf:function(){return this.value}}}),w.extend(w.FX,{attr:function(t,e,n){if("object"==typeof t)for(var i in t)this.attr(i,t[i]);else this.add(t,e,"attrs");return this},css:function(t,e){if("object"==typeof t)for(var n in t)this.css(n,t[n]);else this.add(t,e,"styles");return this},x:function(t,e){if(this.target()instanceof w.G)return this.transform({x:t},e),this;var n=new w.Number(t);return n.relative=e,this.add("x",n)},y:function(t,e){if(this.target()instanceof w.G)return this.transform({y:t},e),this;var n=new w.Number(t);return n.relative=e,this.add("y",n)},cx:function(t){return this.add("cx",new w.Number(t))},cy:function(t){return this.add("cy",new w.Number(t))},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},size:function(t,e){if(this.target()instanceof w.Text)this.attr("font-size",t);else{var n;t&&e||(n=this.target().bbox()),t||(t=n.width/n.height*e),e||(e=n.height/n.width*t),this.add("width",new w.Number(t)).add("height",new w.Number(e))}return this},width:function(t){return this.add("width",new w.Number(t))},height:function(t){return this.add("height",new w.Number(t))},plot:function(t,e,n,i){return 4===arguments.length?this.plot([t,e,n,i]):this.add("plot",new(this.target().MorphArray)(t))},leading:function(t){return this.target().leading?this.add("leading",new w.Number(t)):this},viewbox:function(t,e,n,i){return this.target()instanceof w.Container&&this.add("viewbox",new w.Box(t,e,n,i)),this},update:function(t){if(this.target()instanceof w.Stop){if("number"==typeof t||t instanceof w.Number)return this.update({offset:arguments[0],color:arguments[1],opacity:arguments[2]});null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",t.offset)}return this}}),w.Matrix=w.invent({create:function(t){var e,n=p([1,0,0,1,0,0]);for(t=t instanceof w.Element?t.matrixify():"string"==typeof t?p(t.split(w.regex.delimiter).map(parseFloat)):Array.isArray(t)?p(t):"object"==typeof t?t:6===arguments.length?p([].slice.call(arguments)):n,e=M.length-1;e>=0;--e)this[M[e]]=null!=t[M[e]]?t[M[e]]:n[M[e]]},extend:{clone:function(){return new w.Matrix(this)},transform:function(t){var e=!t.flip||"x"!==t.flip&&"both"!==t.flip?1:-1,n=!t.flip||"y"!==t.flip&&"both"!==t.flip?1:-1,i=t.skew&&t.skew.length?t.skew[0]:isFinite(t.skew)?t.skew:isFinite(t.skewX)?t.skewX:0,r=t.skew&&t.skew.length?t.skew[1]:isFinite(t.skew)?t.skew:isFinite(t.skewY)?t.skewY:0,s=t.scale&&t.scale.length?t.scale[0]*e:isFinite(t.scale)?t.scale*e:isFinite(t.scaleX)?t.scaleX*e:e,o=t.scale&&t.scale.length?t.scale[1]*n:isFinite(t.scale)?t.scale*n:isFinite(t.scaleY)?t.scaleY*n:n,a=t.shear||0,h=t.rotate||0,u=new w.Point(null==t.ox?t.origin:t.ox,t.oy),l=u.x,c=u.y,f=new w.Point(null==t.px?t.position:t.px,t.py,{x:null,y:null}),d=f.x,p=f.y,m=new w.Point(null==t.tx?t.translate:t.tx,t.ty),x=m.x,v=m.y,y=new w.Point(null==t.rx?t.relative:t.rx,t.ry),g=y.x,b=y.y,P=new w.Matrix(this),A=(new w.Matrix).translate(-l,-c).scale(s,o).skew(i,r).shear(a).rotate(h).translate(l,c).translate(g,b).lmultiply(P);if(isFinite(d)||isFinite(p)){var C=new w.Point(l-g,c-b).transform(A),N=d?d-C.x:0,M=p?p-C.y:0;A=A.translate(N,M)}return A=A.translate(x,v)},compose:function(t){var e=t.scaleX||1,n=t.scaleY||1,i=t.shear||0,r=t.rotate||0,s=t.translateX||0,o=t.translateY||0;return(new w.Matrix).scale(e,n).shear(i).rotate(r).translate(s,o).lmultiply(this)},decompose:function(){var t=this.a,e=this.b,n=this.c,i=this.d,r=this.e,s=this.f,o=t*i-e*n,a=o>0?1:-1,h=a*Math.sqrt(t*t+e*e),u=180/Math.PI*Math.atan2(a*e,a*t),l=(t*n+e*i)/o;return{scaleX:h,scaleY:n*h/(l*t-e)||i*h/(l*e+t),shear:l,rotate:u,translateX:r,translateY:s,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f}},morph:function(t){return this.destination=new w.Matrix(t),this},at:function(t){return this.destination?new w.Matrix({a:this.a+(this.destination.a-this.a)*t,b:this.b+(this.destination.b-this.b)*t,c:this.c+(this.destination.c-this.c)*t,d:this.d+(this.destination.d-this.d)*t,e:this.e+(this.destination.e-this.e)*t,f:this.f+(this.destination.f-this.f)*t}):this},multiply:function(t){var e=this,n=new w.Matrix(t),i=e.a*n.a+e.c*n.b,r=e.b*n.a+e.d*n.b,s=e.a*n.c+e.c*n.d,o=e.b*n.c+e.d*n.d,a=e.e+e.a*n.e+e.c*n.f,h=e.f+e.b*n.e+e.d*n.f;return new w.Matrix(i,r,s,o,a,h)},lmultiply:function(t){return new w.Matrix(t).multiply(this)},inverse:function(){return new w.Matrix(this.native().inverse())},translate:function(t,e){var n=new w.Matrix(this);return n.e+=t||0,n.f+=e||0,n},scale:function(t,e,n,i){1===arguments.length?e=t:3===arguments.length&&(i=n,n=e,e=t);var r=new w.Matrix(t,0,0,e,0,0);return this.around(n,i,r)},rotate:function(t,e,n){t=w.utils.radians(t);var i=new w.Matrix(Math.cos(t),Math.sin(t),-Math.sin(t),Math.cos(t),0,0);return this.around(e,n,i)},flip:function(t,e){return"x"===t?this.scale(-1,1,e,0):"y"===t?this.scale(1,-1,0,e):this.scale(-1,-1,t,e||t)},shear:function(t,e,n){var i=new w.Matrix(1,0,t,1,0,0);return this.around(e,n,i)},skew:function(t,e,n,i){1===arguments.length?e=t:3===arguments.length&&(i=n,n=e,e=t),t=w.utils.radians(t),e=w.utils.radians(e);var r=new w.Matrix(1,Math.tan(e),Math.tan(t),1,0,0);return this.around(n,i,r)},skewX:function(t,e,n){return this.skew(t,0,e,n)},skewY:function(t,e,n){return this.skew(0,t,e,n)},around:function(t,e,n){var i=t||0,r=e||0;return this.translate(-i,-r).lmultiply(n).translate(i,r)},native:function(){for(var t=w.parser.nodes.svg.node.createSVGMatrix(),e=M.length-1;e>=0;e--)t[M[e]]=this[M[e]];return t},equals:function(t){var e=new w.Matrix(t);return g(this.a,e.a)&&g(this.b,e.b)&&g(this.c,e.c)&&g(this.d,e.d)&&g(this.e,e.e)&&g(this.f,e.f)},toString:function(){return"matrix("+this.a+","+this.b+","+this.c+","+this.d+","+this.e+","+this.f+")"}},parent:w.Element,construct:{ctm:function(){return new w.Matrix(this.node.getCTM())},screenCTM:function(){if(this instanceof w.Doc&&!this.isRoot()){var t=this.rect(1,1),e=t.node.getScreenCTM();return t.remove(),new w.Matrix(e)}return new w.Matrix(this.node.getScreenCTM())}}}),w.Point=w.invent({create:function(t,e,n){var i;n=n||{x:0,y:0},i=Array.isArray(t)?{x:t[0],y:t[1]}:"object"==typeof t?{x:t.x,y:t.y}:{x:t,y:e},this.x=null==i.x?n.x:i.x,this.y=null==i.y?n.y:i.y},extend:{clone:function(){return new w.Point(this)},morph:function(t,e){return this.destination=new w.Point(t,e),this},at:function(t){return this.destination?new w.Point({x:this.x+(this.destination.x-this.x)*t,y:this.y+(this.destination.y-this.y)*t}):this},native:function(){var t=w.parser.nodes.svg.node.createSVGPoint();return t.x=this.x,t.y=this.y,t},transform:function(t){return new w.Point(this.native().matrixTransform(t.native()))}}}),w.extend(w.Element,{point:function(t,e){return new w.Point(t,e).transform(this.screenCTM().inverse())}}),w.extend(w.Element,{attr:function(t,e,n){if(null==t){for(t={},
-e=this.node.attributes,n=e.length-1;n>=0;n--)t[e[n].nodeName]=w.regex.isNumber.test(e[n].nodeValue)?parseFloat(e[n].nodeValue):e[n].nodeValue;return t}if("object"==typeof t)for(e in t)this.attr(e,t[e]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return e=this.node.getAttribute(t),null==e?w.defaults.attrs[t]:w.regex.isNumber.test(e)?parseFloat(e):e;"fill"!==t&&"stroke"!==t||(w.regex.isImage.test(e)&&(e=this.doc().defs().image(e)),e instanceof w.Image&&(e=this.doc().defs().pattern(0,0,function(){this.add(e)}))),"number"==typeof e?e=new w.Number(e):w.Color.isColor(e)?e=new w.Color(e):Array.isArray(e)&&(e=new w.Array(e)),"leading"===t?this.leading&&this.leading(e):"string"==typeof n?this.node.setAttributeNS(n,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!==t&&"x"!==t||this.rebuild(t,e)}return this}}),w.extend(w.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){return(this.attr("transform")||"").split(w.regex.transforms).slice(0,-1).map(function(t){var e=t.trim().split("(");return[e[0],e[1].split(w.regex.delimiter).map(function(t){return parseFloat(t)})]}).reverse().reduce(function(t,e){return"matrix"===e[0]?t.lmultiply(p(e[1])):t[e[0]].apply(t,e[1])},new w.Matrix)},toParent:function(t){if(this===t)return this;var e=this.screenCTM(),n=t.screenCTM().inverse();return this.addTo(t).untransform().transform(n.multiply(e)),this},toDoc:function(){return this.toParent(this.doc())}}),w.extend(w.Element,{transform:function(t,e){var n=this.bbox();if(null==t||"string"==typeof t){var i=new w.Matrix(this).decompose();return i[t]||i}if(null!=t.a){var r=new w.Matrix(t);if(null!=e){var s=new w.Matrix(this);r=r.multiply(s)}return this.attr("transform",r)}if("string"==typeof t.origin||null==t.origin&&null==t.ox&&null==t.oy){var o="string"==typeof t.origin?t.origin.toLowerCase().trim():"center",a=n.height,h=n.width,u=n.x,l=n.y;t.ox=o.includes("left")?u:o.includes("right")?u+h:u+h/2,t.oy=o.includes("top")?l:o.includes("bottom")?l+a:l+a/2,t.origin=null}var c=new w.Matrix(!0===e?this:e).transform(t);return this.attr("transform",c)}}),w.extend(w.FX,{transform:function(t,e){}}),w.extend(w.Element,{css:function(t,e){var n,i,r={};if(0===arguments.length)return this.node.style.cssText.split(/\s*;\s*/).filter(function(t){return!!t.length}).forEach(function(t){n=t.split(/\s*:\s*/),r[n[0]]=n[1]}),r;if(arguments.length<2){if(Array.isArray(t)){for(i=t.length;i--;)r[u(t[i])]=this.node.style[u(t[i])];return r}if("string"==typeof t)return this.node.style[u(t)];if("object"==typeof t)for(i in t)this.node.style[u(i)]=null==t[i]||w.regex.isBlank.test(t[i])?"":t[i]}return 2===arguments.length&&(this.node.style[u(t)]=null==e||w.regex.isBlank.test(e)?"":e),this}}),w.Parent=w.invent({create:function(t){this.constructor(t)},inherit:w.Element,extend:{children:function(){return w.utils.map(this.node.children,function(t){return w.adopt(t)})},add:function(t,e){return t=n(t),t.node!==this.node.children[e]&&this.node.insertBefore(t.node,this.node.children[e]||null),this},put:function(t,e){return this.add(t,e),t.instance||t},has:function(t){return this.index(t)>=0},index:function(t){return[].slice.call(this.node.children).indexOf(t.node)},get:function(t){return w.adopt(this.node.children[t])},first:function(){return this.get(0)},last:function(){return this.get(this.node.children.length-1)},each:function(t,e){var n,i,r=this.children();for(n=0,i=r.length;n<i;n++)r[n]instanceof w.Element&&t.apply(r[n],[n,r]),e&&r[n]instanceof w.Parent&&r[n].each(t,e);return this},removeElement:function(t){return this.node.removeChild(t.node),this},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return delete this._defs,this}}}),w.extend(w.Parent,{flatten:function(t){return this instanceof w.G||this instanceof w.Doc?(t=t||(this instanceof w.Doc&&this.isRoot()?this:this.parent(w.Parent)),this.each(function(){return this instanceof w.Defs?this:this instanceof w.Parent?this.flatten(t):this.toParent(t)}),this.node.firstElementChild||this.remove(),this):this},ungroup:function(t){return this instanceof w.G||this instanceof w.Doc&&!this.isRoot()?(t=t||this.parent(w.Parent),this.each(function(){return this.toParent(t)}),this.remove(),this):this}}),w.Container=w.invent({create:function(t){this.constructor(t)},inherit:w.Parent}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","mouseenter","mouseleave","touchstart","touchmove","touchleave","touchend","touchcancel"].forEach(function(t){w.Element.prototype[t]=function(e){return w.on(this,t,e),this}}),w.listenerId=0,w.on=function(t,e,n,i,r){var s=n.bind(i||t),o=t instanceof w.Element?t.node:t;o.instance=o.instance||{events:{}};var a=o.instance.events;n._svgjsListenerId||(n._svgjsListenerId=++w.listenerId),e.split(w.regex.delimiter).forEach(function(t){var e=t.split(".")[0],i=t.split(".")[1]||"*";a[e]=a[e]||{},a[e][i]=a[e][i]||{},a[e][i][n._svgjsListenerId]=s,o.addEventListener(e,s,r||!1)})},w.off=function(t,e,n,i){var r=t instanceof w.Element?t.node:t;if(r.instance&&("function"!=typeof n||(n=n._svgjsListenerId))){var s=r.instance.events;(e||"").split(w.regex.delimiter).forEach(function(t){var e,o,a=t&&t.split(".")[0],h=t&&t.split(".")[1];if(n)s[a]&&s[a][h||"*"]&&(r.removeEventListener(a,s[a][h||"*"][n],i||!1),delete s[a][h||"*"][n]);else if(a&&h){if(s[a]&&s[a][h]){for(o in s[a][h])w.off(r,[a,h].join("."),o);delete s[a][h]}}else if(h)for(t in s)for(e in s[t])h===e&&w.off(r,[t,h].join("."));else if(a){if(s[a]){for(e in s[a])w.off(r,[a,e].join("."));delete s[a]}}else{for(t in s)w.off(r,t);r.instance.events={}}})}},w.extend(w.Element,{on:function(t,e,n,i){return w.on(this,t,e,n,i),this},off:function(t,e){return w.off(this.node,t,e),this},dispatch:function(e,n){return e instanceof t.Event?this.node.dispatchEvent(e):this.node.dispatchEvent(e=new t.CustomEvent(e,{detail:n,cancelable:!0})),e},fire:function(t,e){return this.dispatch(t,e),this}}),w.Defs=w.invent({create:"defs",inherit:w.Container}),w.G=w.invent({create:"g",inherit:w.Container,extend:{},construct:{group:function(){return this.put(new w.G)}}}),w.extend(w.Element,{siblings:function(){return this.parent().children()},position:function(){return this.parent().index(this)},next:function(){return this.siblings()[this.position()+1]},prev:function(){return this.siblings()[this.position()-1]},forward:function(){var t=this.position()+1,e=this.parent();return e.removeElement(this).add(this,t),e instanceof w.Doc&&e.node.appendChild(e.defs().node),this},backward:function(){var t=this.position();return t>0&&this.parent().removeElement(this).add(this,t-1),this},front:function(){var t=this.parent();return t.node.appendChild(this.node),t instanceof w.Doc&&t.node.appendChild(t.defs().node),this},back:function(){return this.position()>0&&this.parent().removeElement(this).add(this,0),this},before:function(t){t.remove();var e=this.position();return this.parent().add(t,e),this},after:function(t){t.remove();var e=this.position();return this.parent().add(t,e+1),this}}),w.Mask=w.invent({create:"mask",inherit:w.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unmask()}),w.Element.prototype.remove.call(this)},targets:function(){return w.select('svg [mask*="'+this.id()+'"]')}},construct:{mask:function(){return this.defs().put(new w.Mask)}}}),w.extend(w.Element,{maskWith:function(t){var e=t instanceof w.Mask?t:this.parent().mask().add(t);return this.attr("mask",'url("#'+e.id()+'")')},unmask:function(){return this.attr("mask",null)},masker:function(){return this.reference("mask")}}),w.ClipPath=w.invent({create:"clipPath",inherit:w.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unclip()}),w.Element.prototype.remove.call(this)},targets:function(){return w.select('svg [clip-path*="'+this.id()+'"]')}},construct:{clip:function(){return this.defs().put(new w.ClipPath)}}}),w.extend(w.Element,{clipWith:function(t){var e=t instanceof w.ClipPath?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.id()+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}),w.Gradient=w.invent({create:function(t){this.constructor("object"==typeof t?t:w.create(t+"Gradient"))},inherit:w.Container,extend:{stop:function(t,e,n){return this.put(new w.Stop).update(t,e,n)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},url:function(){return"url(#"+this.id()+")"},toString:function(){return this.url()},attr:function(t,e,n){return"transform"===t&&(t="gradientTransform"),w.Container.prototype.attr.call(this,t,e,n)}},construct:{gradient:function(t,e){return this.defs().gradient(t,e)}}}),w.extend([w.Gradient,w.FX],{from:function(t,e){return"radialGradient"===(this._target||this).type?this.attr({fx:new w.Number(t),fy:new w.Number(e)}):this.attr({x1:new w.Number(t),y1:new w.Number(e)})},to:function(t,e){return"radialGradient"===(this._target||this).type?this.attr({cx:new w.Number(t),cy:new w.Number(e)}):this.attr({x2:new w.Number(t),y2:new w.Number(e)})}}),w.extend(w.Defs,{gradient:function(t,e){return this.put(new w.Gradient(t)).update(e)}}),w.Stop=w.invent({create:"stop",inherit:w.Element,extend:{update:function(t){return("number"==typeof t||t instanceof w.Number)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new w.Number(t.offset)),this}}}),w.Pattern=w.invent({create:"pattern",inherit:w.Container,extend:{url:function(){return"url(#"+this.id()+")"},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return this.url()},attr:function(t,e,n){return"transform"===t&&(t="patternTransform"),w.Container.prototype.attr.call(this,t,e,n)}},construct:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}}}),w.extend(w.Defs,{pattern:function(t,e,n){return this.put(new w.Pattern).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}),w.Doc=w.invent({create:function(t){this.constructor(t||w.create("svg")),this.namespace()},inherit:w.Container,extend:{isRoot:function(){return!(this.node.parentNode&&this.node.parentNode instanceof t.SVGElement&&"#document"!==this.node.parentNode.nodeName)},doc:function(){return this.isRoot()?this:w.Element.prototype.doc.call(this)},namespace:function(){return this.isRoot()?this.attr({xmlns:w.ns,version:"1.1"}).attr("xmlns:xlink",w.xlink,w.xmlns).attr("xmlns:svgjs",w.svgjs,w.xmlns):this.doc().namespace()},defs:function(){return this.isRoot()?w.adopt(this.node.getElementsByTagName("defs")[0])||this.put(new w.Defs):this.doc().defs()},parent:function(t){return this.isRoot()?"#document"===this.node.parentNode.nodeName?null:this.node.parentNode:w.Element.prototype.parent.call(this,t)},remove:function(){return this.isRoot()?(this.parent()&&this.parent().removeChild(this.node),this):w.Element.prototype.remove.call(this)},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this}},construct:{nested:function(){return this.put(new w.Doc)}}}),w.Shape=w.invent({create:function(t){this.constructor(t)},inherit:w.Element}),w.Bare=w.invent({create:function(t,e){if(this.constructor(w.create(t)),e)for(var n in e.prototype)"function"==typeof e.prototype[n]&&(this[n]=e.prototype[n])},inherit:w.Element,extend:{words:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(e.createTextNode(t)),this}}}),w.extend(w.Parent,{element:function(t,e){return this.put(new w.Bare(t,e))}}),w.Symbol=w.invent({create:"symbol",inherit:w.Container,construct:{symbol:function(){return this.put(new w.Symbol)}}}),w.Use=w.invent({create:"use",inherit:w.Shape,extend:{element:function(t,e){return this.attr("href",(e||"")+"#"+t,w.xlink)}},construct:{use:function(t,e){return this.put(new w.Use).element(t,e)}}}),w.Rect=w.invent({create:"rect",inherit:w.Shape,construct:{rect:function(t,e){return this.put(new w.Rect).size(t,e)}}}),w.Circle=w.invent({create:"circle",inherit:w.Shape,construct:{circle:function(t){return this.put(new w.Circle).rx(new w.Number(t).divide(2)).move(0,0)}}}),w.extend([w.Circle,w.FX],{rx:function(t){return this.attr("r",t)},ry:function(t){return this.rx(t)}}),w.Ellipse=w.invent({create:"ellipse",inherit:w.Shape,construct:{ellipse:function(t,e){return this.put(new w.Ellipse).size(t,e).move(0,0)}}}),w.extend([w.Ellipse,w.Rect,w.FX],{rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)}}),w.extend([w.Circle,w.Ellipse],{x:function(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())},y:function(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())},cx:function(t){return null==t?this.attr("cx"):this.attr("cx",t)},cy:function(t){return null==t?this.attr("cy"):this.attr("cy",t)},width:function(t){return null==t?2*this.rx():this.rx(new w.Number(t).divide(2))},height:function(t){return null==t?2*this.ry():this.ry(new w.Number(t).divide(2))},size:function(t,e){var n=d(this,t,e);return this.rx(new w.Number(n.width).divide(2)).ry(new w.Number(n.height).divide(2))}}),w.Line=w.invent({create:"line",inherit:w.Shape,extend:{array:function(){return new w.PointArray([[this.attr("x1"),this.attr("y1")],[this.attr("x2"),this.attr("y2")]])},plot:function(t,e,n,i){return null==t?this.array():(t=void 0!==e?{x1:t,y1:e,x2:n,y2:i}:new w.PointArray(t).toLine(),this.attr(t))},move:function(t,e){return this.attr(this.array().move(t,e).toLine())},size:function(t,e){var n=d(this,t,e);return this.attr(this.array().size(n.width,n.height).toLine())}},construct:{line:function(t,e,n,i){return w.Line.prototype.plot.apply(this.put(new w.Line),null!=t?[t,e,n,i]:[0,0,0,0])}}}),w.Polyline=w.invent({create:"polyline",inherit:w.Shape,construct:{polyline:function(t){return this.put(new w.Polyline).plot(t||new w.PointArray)}}}),w.Polygon=w.invent({create:"polygon",inherit:w.Shape,construct:{polygon:function(t){return this.put(new w.Polygon).plot(t||new w.PointArray)}}}),w.extend([w.Polyline,w.Polygon],{array:function(){return this._array||(this._array=new w.PointArray(this.attr("points")))},plot:function(t){return null==t?this.array():this.clear().attr("points","string"==typeof t?t:this._array=new w.PointArray(t))},clear:function(){return delete this._array,this},move:function(t,e){return this.attr("points",this.array().move(t,e))},size:function(t,e){var n=d(this,t,e);return this.attr("points",this.array().size(n.width,n.height))}}),w.extend([w.Line,w.Polyline,w.Polygon],{MorphArray:w.PointArray,x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},width:function(t){var e=this.bbox();return null==t?e.width:this.size(t,e.height)},height:function(t){var e=this.bbox();return null==t?e.height:this.size(e.width,t)}}),w.Path=w.invent({create:"path",inherit:w.Shape,extend:{MorphArray:w.PathArray,array:function(){return this._array||(this._array=new w.PathArray(this.attr("d")))},plot:function(t){return null==t?this.array():this.clear().attr("d","string"==typeof t?t:this._array=new w.PathArray(t))},clear:function(){return delete this._array,this},move:function(t,e){return this.attr("d",this.array().move(t,e))},x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},size:function(t,e){var n=d(this,t,e);return this.attr("d",this.array().size(n.width,n.height))},width:function(t){return null==t?this.bbox().width:this.size(t,this.bbox().height)},height:function(t){return null==t?this.bbox().height:this.size(this.bbox().width,t)}},construct:{path:function(t){return this.put(new w.Path).plot(t||new w.PathArray)}}}),w.Image=w.invent({create:"image",inherit:w.Shape,extend:{load:function(e,n){if(!e)return this;var i=new t.Image;return w.on(i,"load",function(t){var r=this.parent(w.Pattern);0===this.width()&&0===this.height()&&this.size(i.width,i.height),r instanceof w.Pattern&&0===r.width()&&0===r.height()&&r.size(this.width(),this.height()),"function"==typeof n&&n.call(this,{width:i.width,height:i.height,ratio:i.width/i.height,url:e})},this),w.on(i,"load error",function(){w.off(i)}),this.attr("href",i.src=e,w.xlink)}},construct:{image:function(t,e){return this.put(new w.Image).size(0,0).load(t,e)}}}),w.Text=w.invent({create:function(t){this.constructor(t||w.create("text")),this.dom.leading=new w.Number(1.3),this._rebuild=!0,this._build=!1,this.attr("font-family",w.defaults.attrs["font-family"])},inherit:w.Parent,extend:{x:function(t){return null==t?this.attr("x"):this.attr("x",t)},y:function(t){var e=this.attr("y"),n="number"==typeof e?e-this.bbox().y:0;return null==t?"number"==typeof e?e-n:e:this.attr("y","number"==typeof t?t+n:t)},cx:function(t){return null==t?this.bbox().cx:this.x(t-this.bbox().width/2)},cy:function(t){return null==t?this.bbox().cy:this.y(t-this.bbox().height/2)},text:function(t){if(void 0===t){var e=this.node.childNodes,n=0;t="";for(var i=0,r=e.length;i<r;++i)"textPath"!==e[i].nodeName?(i!==n&&3!==e[i].nodeType&&!0===w.adopt(e[i]).dom.newLined&&(t+="\n"),t+=e[i].textContent):0===i&&(n=1);return t}if(this.clear().build(!0),"function"==typeof t)t.call(this,this);else{t=t.split("\n");for(var s=0,o=t.length;s<o;s++)this.tspan(t[s]).newLine()}return this.build(!1).rebuild()},leading:function(t){return null==t?this.dom.leading:(this.dom.leading=new w.Number(t),this.rebuild())},rebuild:function(t){if("boolean"==typeof t&&(this._rebuild=t),this._rebuild){var e=this,n=0,i=this.dom.leading*new w.Number(this.attr("font-size"));this.each(function(){this.dom.newLined&&(this.attr("x",e.attr("x")),"\n"===this.text()?n+=i:(this.attr("dy",i+n),n=0))}),this.fire("rebuild")}return this},build:function(t){return this._build=!!t,this},setData:function(t){return this.dom=t,this.dom.leading=new w.Number(t.leading||1.3),this}},construct:{text:function(t){return this.put(new w.Text).text(t)},plain:function(t){return this.put(new w.Text).plain(t)}}}),w.Tspan=w.invent({create:"tspan",inherit:w.Parent,extend:{text:function(t){return null==t?this.node.textContent+(this.dom.newLined?"\n":""):("function"==typeof t?t.call(this,this):this.plain(t),this)},dx:function(t){return this.attr("dx",t)},dy:function(t){return this.attr("dy",t)},newLine:function(){var t=this.parent(w.Text);return this.dom.newLined=!0,this.dy(t.dom.leading*t.attr("font-size")).attr("x",t.x())}}}),w.extend([w.Text,w.Tspan],{plain:function(t){return!1===this._build&&this.clear(),this.node.appendChild(e.createTextNode(t)),this},tspan:function(t){var e=new w.Tspan;return this._build||this.clear(),this.node.appendChild(e.node),e.text(t)},length:function(){return this.node.getComputedTextLength()}}),w.TextPath=w.invent({create:"textPath",inherit:w.Text,parent:w.Parent,extend:{MorphArray:w.PathArray,array:function(){var t=this.track();return t?t.array():null},plot:function(t){var e=this.track(),n=null;return e&&(n=e.plot(t)),null==t?n:this},track:function(){return this.reference("href")}},construct:{textPath:function(t,e){return this.defs().path(e).text(t).addTo(this)}}}),w.extend([w.Text],{path:function(t){var e=new w.TextPath;return t instanceof w.Path||(t=this.doc().defs().path(t)),e.attr("href","#"+t,w.xlink),this.put(e)},textPath:function(){return this.select("textPath")}}),w.extend([w.Path],{text:function(t){if(t instanceof w.Text){var e=t.text();return t.clear().path(this).text(e)}return this.parent().put(new w.Text).path(this).text(t)}}),w.A=w.invent({create:"a",inherit:w.Container,extend:{to:function(t){return this.attr("href",t,w.xlink)},target:function(t){return this.attr("target",t)}},construct:{link:function(t){return this.put(new w.A).to(t)}}}),w.extend(w.Element,{linkTo:function(t){var e=new w.A;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}),w.Marker=w.invent({create:"marker",inherit:w.Container,extend:{width:function(t){return this.attr("markerWidth",t)},height:function(t){return this.attr("markerHeight",t)},ref:function(t,e){return this.attr("refX",t).attr("refY",e)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return"url(#"+this.id()+")"}},construct:{marker:function(t,e,n){return this.defs().marker(t,e,n)}}}),w.extend(w.Defs,{marker:function(t,e,n){return this.put(new w.Marker).size(t,e).ref(t/2,e/2).viewbox(0,0,t,e).attr("orient","auto").update(n)}}),w.extend([w.Line,w.Polyline,w.Polygon,w.Path],{marker:function(t,e,n,i){var r=["marker"];return"all"!==t&&r.push(t),r=r.join("-"),t=arguments[1]instanceof w.Marker?arguments[1]:this.doc().marker(e,n,i),this.attr(r,t)}});var N={stroke:["color","width","opacity","linecap","linejoin","miterlimit","dasharray","dashoffset"],fill:["color","opacity","rule"],prefix:function(t,e){return"color"===e?t:t+"-"+e}};["fill","stroke"].forEach(function(t){var e,n={};n[t]=function(n){if(void 0===n)return this;if("string"==typeof n||w.Color.isRgb(n)||n&&"function"==typeof n.fill)this.attr(t,n);else for(e=N[t].length-1;e>=0;e--)null!=n[N[t][e]]&&this.attr(N.prefix(t,N[t][e]),n[N[t][e]]);return this},w.extend([w.Element,w.FX],n)}),w.extend([w.Element,w.FX],{matrix:function(t,e,n,i,r,s){return null==t?new w.Matrix(this):this.attr("transform",new w.Matrix(t,e,n,i,r,s))},rotate:function(t,e,n){return this.transform({rotate:t,ox:e,oy:n},!0)},skew:function(t,e,n,i){return 1===arguments.length||3===arguments.length?this.transform({skew:t,ox:e,oy:n},!0):this.transform({skew:[t,e],ox:n,oy:i},!0)},shear:function(t,e,n){return this.transform({shear:t,ox:e,oy:n},!0)},scale:function(t,e,n,i){return 1===arguments.length||3===arguments.length?this.transform({scale:t,ox:e,oy:n},!0):this.transform({scale:[t,e],ox:n,oy:i},!0)},translate:function(t,e){return this.transform({translate:[t,e]},!0)},relative:function(t,e){return this.transform({relative:[t,e]},!0)},flip:function(t,e){var n="string"==typeof t?t:(isFinite(t),"both"),i="both"===t&&isFinite(e)?[e,e]:"x"===t?[e,0]:"y"===t?[0,e]:isFinite(t)?[t,t]:[0,0];this.transform({flip:n,origin:i},!0)},opacity:function(t){return this.attr("opacity",t)},dx:function(t){return this.x(new w.Number(t).plus(this instanceof w.FX?0:this.x()),!0)},dy:function(t){return this.y(new w.Number(t).plus(this instanceof w.FX?0:this.y()),!0)},dmove:function(t,e){return this.dx(t).dy(e)}}),w.extend([w.Rect,w.Ellipse,w.Circle,w.Gradient,w.FX],{radius:function(t,e){var n=(this._target||this).type;return"radialGradient"===n||"radialGradient"===n?this.attr("r",new w.Number(t)):this.rx(t).ry(null==e?t:e)}}),w.extend(w.Path,{length:function(){return this.node.getTotalLength()},pointAt:function(t){return new w.Point(this.node.getPointAtLength(t))}}),w.extend([w.Parent,w.Text,w.Tspan,w.FX],{font:function(t,e){if("object"==typeof t)for(e in t)this.font(e,t[e]);return"leading"===t?this.leading(e):"anchor"===t?this.attr("text-anchor",e):"size"===t||"family"===t||"weight"===t||"stretch"===t||"variant"===t||"style"===t?this.attr("font-"+t,e):this.attr(t,e)}}),w.extend(w.Element,{data:function(t,e,n){if("object"==typeof t)for(e in t)this.data(e,t[e]);else if(arguments.length<2)try{return JSON.parse(this.attr("data-"+t))}catch(e){return this.attr("data-"+t)}else this.attr("data-"+t,null===e?null:!0===n||"string"==typeof e||"number"==typeof e?e:JSON.stringify(e));return this}}),w.extend(w.Element,{remember:function(t,e){if("object"==typeof arguments[0])for(var n in t)this.remember(n,t[n]);else{if(1===arguments.length)return this.memory()[t];this.memory()[t]=e}return this},forget:function(){if(0===arguments.length)this._memory={};else for(var t=arguments.length-1;t>=0;t--)delete this.memory()[arguments[t]];return this},memory:function(){return this._memory||(this._memory={})}}),w.get=function(t){var n=e.getElementById(y(t)||t);return w.adopt(n)},w.select=function(t,n){return w.utils.map((n||e).querySelectorAll(t),function(t){return w.adopt(t)})},w.$$=function(t,n){return w.utils.map((n||e).querySelectorAll(t),function(t){return w.adopt(t)})},w.$=function(t,n){return w.adopt((n||e).querySelector(t))},w.extend(w.Parent,{select:function(t){return w.select(t,this.node)}});var M="abcdef".split("");return w.Box=w.invent({create:function(t){var e=[0,0,0,0];t="string"==typeof t?t.split(w.regex.delimiter).map(parseFloat):Array.isArray(t)?t:"object"==typeof t?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4===arguments.length?[].slice.call(arguments):e,this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],v(this)},extend:{merge:function(t){var e=Math.min(this.x,t.x),n=Math.min(this.y,t.y);return new w.Box(e,n,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-n)},transform:function(t){var e=1/0,n=-1/0,i=1/0,r=-1/0;return[new w.Point(this.x,this.y),new w.Point(this.x2,this.y),new w.Point(this.x,this.y2),new w.Point(this.x2,this.y2)].forEach(function(s){s=s.transform(t),e=Math.min(e,s.x),n=Math.max(n,s.x),i=Math.min(i,s.y),r=Math.max(r,s.y)}),new w.Box(e,i,n-e,r-i)},addOffset:function(){return this.x+=t.pageXOffset,this.y+=t.pageYOffset,this},toString:function(){return this.x+" "+this.y+" "+this.width+" "+this.height},morph:function(t,e,n,i){return this.destination=new w.Box(t,e,n,i),this},at:function(t){return this.destination?new w.Box(this.x+(this.destination.x-this.x)*t,this.y+(this.destination.y-this.y)*t,this.width+(this.destination.width-this.width)*t,this.height+(this.destination.height-this.height)*t):this}},parent:w.Element,construct:{bbox:function(){var t;try{if(t=this.node.getBBox(),i(t)&&!r(this.node))throw new Exception("Element not in the dom")}catch(n){try{var e=this.clone(w.parser().svg).show();t=e.node.getBBox(),e.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return new w.Box(t)},rbox:function(t){try{var e=new w.Box(this.node.getBoundingClientRect());return t?e.transform(t.screenCTM().inverse()):e.addOffset()}catch(t){return new w.Box}}}}),w.extend([w.Doc,w.Symbol,w.Image,w.Pattern,w.Marker,w.ForeignObject,w.View],{viewbox:function(t,e,n,i){return null==t?new w.Box(this.attr("viewBox")):this.attr("viewBox",new w.Box(t,e,n,i))}}),w.parser=function(){var t;return w.parser.nodes.svg.node.parentNode||(t=e.body||e.documentElement,w.parser.nodes.svg.addTo(t)),w.parser.nodes},w.parser.nodes={svg:w().size(2,0).css({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"})},w.parser.nodes.path=w.parser.nodes.svg.path().node,w}); \ No newline at end of file
+/*! svg.js v3.0.0 MIT*/;!function(t,e){"function"==typeof define&&define.amd?define(function(){return e(t,t.document)}):"object"==typeof exports?module.exports=t.document?e(t,t.document):function(t){return e(t,t.document)}:t.SVG=e(t,t.document)}("undefined"!=typeof window?window:this,function(t,e){function i(t,i){if(t instanceof w.Element)return t;if("object"==typeof t)return w.adopt(t);if(null==t)return new w.Doc;if("string"==typeof t&&"<"!==t.charAt(0))return w.adopt(e.querySelector(t));var n=w.create("svg");return n.innerHTML=t,t=w.adopt(n.firstElementChild)}function n(t){return!(t.w||t.h||t.x||t.y)}function r(t){return(e.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t===e}).call(e.documentElement,t)}function s(t,e,i,n){return i+n.replace(w.regex.dots," .")}function o(t){for(var e=t.slice(0),i=e.length;i--;)Array.isArray(e[i])&&(e[i]=o(e[i]));return e}function a(t,e){return t instanceof e}function h(t,e){return(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)}function u(t){return t.toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()})}function l(t){return t.charAt(0).toUpperCase()+t.slice(1)}function c(t){return 4===t.length?["#",t.substring(1,2),t.substring(1,2),t.substring(2,3),t.substring(2,3),t.substring(3,4),t.substring(3,4)].join(""):t}function f(t){var e=t.toString(16);return 1===e.length?"0"+e:e}function d(t,e,i){if(null==e||null==i){var n=t.bbox();null==e?e=n.width/n.height*i:null==i&&(i=n.height/n.width*e)}return{width:e,height:i}}function p(t){return{a:t[0],b:t[1],c:t[2],d:t[3],e:t[4],f:t[5]}}function m(t){for(var e=0,i=t.length,n="";e<i;e++)n+=t[e][0],null!=t[e][1]&&(n+=t[e][1],null!=t[e][2]&&(n+=" ",n+=t[e][2],null!=t[e][3]&&(n+=" ",n+=t[e][3],n+=" ",n+=t[e][4],null!=t[e][5]&&(n+=" ",n+=t[e][5],n+=" ",n+=t[e][6],null!=t[e][7]&&(n+=" ",n+=t[e][7])))));return n+" "}function v(t){for(var e=t.children.length-1;e>=0;e--)v(t.children[e]);return t.id?w.adopt(t).id(w.eid(t.nodeName)):w.adopt(t)}function x(t){return null==t.x&&(t.x=0,t.y=0,t.width=0,t.height=0),t.w=t.width,t.h=t.height,t.x2=t.x+t.width,t.y2=t.y+t.height,t.cx=t.x+t.width/2,t.cy=t.y+t.height/2,t}function y(t){var e=(t||"").toString().match(w.regex.reference);if(e)return e[1]}function g(t,e,i){return Math.abs(e-t)<(i||1e-6)}if(!e.createElementNS||!e.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect)return{supported:!1};var w=this.SVG=function(t){if(w.supported)return t=i(t)};w.supported=!0,w.ns="http://www.w3.org/2000/svg",w.xmlns="http://www.w3.org/2000/xmlns/",w.xlink="http://www.w3.org/1999/xlink",w.svgjs="http://svgjs.com/svgjs",w.did=1e3,w.eid=function(t){return"Svgjs"+l(t)+w.did++},w.create=function(t){return e.createElementNS(this.ns,t)},w.extend=function(t,e){var i,n;for(t=Array.isArray(t)?t:[t],n=t.length-1;n>=0;n--)if(t[n])for(i in e)t[n].prototype[i]=e[i]},w.invent=function(t){var e="function"==typeof t.create?t.create:function(e){this.constructor(e||w.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&w.extend(e,t.extend),t.construct&&w.extend(t.parent||w.Container,t.construct),e},w.adopt=function(e){if(!e)return null;if(e.instance instanceof w.Element)return e.instance;if(!(e instanceof t.SVGElement))return new w.HtmlNode(e);return"svg"===e.nodeName?new w.Doc(e):"linearGradient"===e.nodeName||"radialGradient"===e.nodeName?new w.Gradient(e):w[l(e.nodeName)]?new(w[l(e.nodeName)])(e):new w.Parent(e)},w.regex={numberAndUnit:/^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+)\)/,reference:/#([a-z0-9\-_]+)/i,transforms:/\)\s*,?\s*/,whitespace:/\s/g,isHex:/^#[a-f0-9]{3,6}$/i,isRgb:/^rgb\(/,isCss:/[^:]+:[^;]+;?/,isBlank:/^(\s+)?$/,isNumber:/^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,isPercent:/^-?[\d.]+%$/,isImage:/\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,delimiter:/[\s,]+/,hyphen:/([^e])-/gi,pathLetters:/[MLHVCSQTAZ]/gi,isPathLetter:/[MLHVCSQTAZ]/i,numbersWithDots:/((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi,dots:/\./g},w.utils={map:function(t,e){var i,n=t.length,r=[];for(i=0;i<n;i++)r.push(e(t[i]));return r},filter:function(t,e){var i,n=t.length,r=[];for(i=0;i<n;i++)e(t[i])&&r.push(t[i]);return r},radians:function(t){return t%360*Math.PI/180},degrees:function(t){return 180*t/Math.PI%360},filterSVGElements:function(e){return this.filter(e,function(e){return e instanceof t.SVGElement})}},w.defaults={attrs:{"fill-opacity":1,"stroke-opacity":1,"stroke-width":0,"stroke-linejoin":"miter","stroke-linecap":"butt",fill:"#000000",stroke:"#000000",opacity:1,x:0,y:0,cx:0,cy:0,width:0,height:0,r:0,rx:0,ry:0,offset:0,"stop-opacity":1,"stop-color":"#000000","font-size":16,"font-family":"Helvetica, Arial, sans-serif","text-anchor":"start"}},w.Queue=w.invent({create:function(){this._first=null,this._last=null,this.length=0,this.id=0},extend:{push:function(t){var e={id:this.id++,value:t};this._last?this._last=this._last.next=e:this._last=this._first=e,this.length++},shift:function(){if(0!=this.length){var t=this._first;return this._first=t.next,this._last=--this.length?this._last:null,t.value}},first:function(){return this._first&&this._first.value},last:function(){return this._last&&this._last.value},remove:function(t){for(var e=null,i=this._first;i&&!t(i);)e=i,i=i.next;if(i&&i===this._first&&(this._first=this._first.next),i&&i===this._last&&(this._last=e),i)return--this.length,e&&(e.next=i.next),i.item}}}),w.Draw={nextDraw:null,frames:new w.Queue,timeouts:new w.Queue,frameCount:0,timeoutCount:0,timer:t.performance||t.Date,frame:function(t){return w.Draw.frames.push({id:w.Draw.frameCount,run:t}),null===w.Draw.nextDraw&&(w.Draw.nextDraw=requestAnimationFrame(w.Draw._draw)),++w.Draw.frameCount},timeout:function(t,e){e=e||0;var i=w.Draw.timer.now()+e,n=w.Draw.timeoutCount++;return w.Draw.timeouts.push({id:n,run:t,time:i}),null===w.Draw.nextDraw&&(w.Draw.nextDraw=requestAnimationFrame(w.Draw._draw)),n},cancelTimeout:function(t){return w.Draw.timeouts.remove(function(e){return e.id==t})},_draw:function(t){for(var e=null,i=w.Draw.timeouts.last();(e=w.Draw.timeouts.shift())&&(t>e.time?e.run():w.Draw.timeouts.push(e),e!==i););for(var n=(w.Draw.frames.last(),w.Draw.frameCount);w.Draw.frames.first()&&w.Draw.frames.first().id<n;){w.Draw.frames.shift().run(t)}w.Draw.nextDraw=w.Draw.timeouts.length>0||w.Draw.frames.length>0?requestAnimationFrame(w.Draw._draw):null}},w.Color=function(t){var e;this.r=0,this.g=0,this.b=0,t&&("string"==typeof t?w.regex.isRgb.test(t)?(e=w.regex.rgb.exec(t.replace(w.regex.whitespace,"")),this.r=parseInt(e[1]),this.g=parseInt(e[2]),this.b=parseInt(e[3])):w.regex.isHex.test(t)&&(e=w.regex.hex.exec(c(t)),this.r=parseInt(e[1],16),this.g=parseInt(e[2],16),this.b=parseInt(e[3],16)):"object"==typeof t&&(this.r=t.r,this.g=t.g,this.b=t.b))},w.extend(w.Color,{toString:function(){return this.toHex()},toHex:function(){return"#"+f(this.r)+f(this.g)+f(this.b)},toRgb:function(){return"rgb("+[this.r,this.g,this.b].join()+")"},brightness:function(){return this.r/255*.3+this.g/255*.59+this.b/255*.11},morph:function(t){return this.destination=new w.Color(t),this},at:function(t){return this.destination?(t=t<0?0:t>1?1:t,new w.Color({r:~~(this.r+(this.destination.r-this.r)*t),g:~~(this.g+(this.destination.g-this.g)*t),b:~~(this.b+(this.destination.b-this.b)*t)})):this}}),w.Color.test=function(t){return t+="",w.regex.isHex.test(t)||w.regex.isRgb.test(t)},w.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},w.Color.isColor=function(t){return w.Color.isRgb(t)||w.Color.test(t)},w.Array=function(t,e){t=(t||[]).valueOf(),0===t.length&&e&&(t=e.valueOf()),this.value=this.parse(t)},w.extend(w.Array,{morph:function(t){if(this.destination=this.parse(t),this.value.length!==this.destination.length){for(var e=this.value[this.value.length-1],i=this.destination[this.destination.length-1];this.value.length>this.destination.length;)this.destination.push(i);for(;this.value.length<this.destination.length;)this.value.push(e)}return this},settle:function(){for(var t=0,e=this.value.length,i=[];t<e;t++)-1===i.indexOf(this.value[t])&&i.push(this.value[t]);return this.value=i,i},at:function(t){if(!this.destination)return this;for(var e=0,i=this.value.length,n=[];e<i;e++)n.push(this.value[e]+(this.destination[e]-this.value[e])*t);return new w.Array(n)},toString:function(){return this.value.join(" ")},valueOf:function(){return this.value},parse:function(t){return t=t.valueOf(),Array.isArray(t)?t:t.trim().split(w.regex.delimiter).map(parseFloat)},reverse:function(){return this.value.reverse(),this},clone:function(){var t=new this.constructor;return t.value=o(this.value),t}}),w.PointArray=function(t,e){w.Array.call(this,t,e||[[0,0]])},w.PointArray.prototype=new w.Array,w.PointArray.prototype.constructor=w.PointArray,w.extend(w.PointArray,{toString:function(){for(var t=0,e=this.value.length,i=[];t<e;t++)i.push(this.value[t].join(","));return i.join(" ")},toLine:function(){return{x1:this.value[0][0],y1:this.value[0][1],x2:this.value[1][0],y2:this.value[1][1]}},at:function(t){if(!this.destination)return this;for(var e=0,i=this.value.length,n=[];e<i;e++)n.push([this.value[e][0]+(this.destination[e][0]-this.value[e][0])*t,this.value[e][1]+(this.destination[e][1]-this.value[e][1])*t]);return new w.PointArray(n)},parse:function(t){var e=[];if(t=t.valueOf(),Array.isArray(t)){if(Array.isArray(t[0]))return t}else t=t.trim().split(w.regex.delimiter).map(parseFloat);t.length%2!=0&&t.pop();for(var i=0,n=t.length;i<n;i+=2)e.push([t[i],t[i+1]]);return e},move:function(t,e){var i=this.bbox();if(t-=i.x,e-=i.y,!isNaN(t)&&!isNaN(e))for(var n=this.value.length-1;n>=0;n--)this.value[n]=[this.value[n][0]+t,this.value[n][1]+e];return this},size:function(t,e){var i,n=this.bbox();for(i=this.value.length-1;i>=0;i--)n.width&&(this.value[i][0]=(this.value[i][0]-n.x)*t/n.width+n.x),n.height&&(this.value[i][1]=(this.value[i][1]-n.y)*e/n.height+n.y);return this},bbox:function(){var t=-1/0,e=-1/0,i=1/0,n=1/0;return this.value.forEach(function(r){t=Math.max(r[0],t),e=Math.max(r[1],e),i=Math.min(r[0],i),n=Math.min(r[1],n)}),{x:i,y:n,width:t-i,height:e-n}}});for(var b={M:function(t,e,i){return e.x=i.x=t[0],e.y=i.y=t[1],["M",e.x,e.y]},L:function(t,e){return e.x=t[0],e.y=t[1],["L",t[0],t[1]]},H:function(t,e){return e.x=t[0],["H",t[0]]},V:function(t,e){return e.y=t[0],["V",t[0]]},C:function(t,e){return e.x=t[4],e.y=t[5],["C",t[0],t[1],t[2],t[3],t[4],t[5]]},S:function(t,e){return e.x=t[2],e.y=t[3],["S",t[0],t[1],t[2],t[3]]},Q:function(t,e){return e.x=t[2],e.y=t[3],["Q",t[0],t[1],t[2],t[3]]},T:function(t,e){return e.x=t[0],e.y=t[1],["T",t[0],t[1]]},Z:function(t,e,i){return e.x=i.x,e.y=i.y,["Z"]},A:function(t,e){return e.x=t[5],e.y=t[6],["A",t[0],t[1],t[2],t[3],t[4],t[5],t[6]]}},P="mlhvqtcsaz".split(""),A=0,C=P.length;A<C;++A)b[P[A]]=function(t){return function(e,i,n){if("H"===t)e[0]=e[0]+i.x;else if("V"===t)e[0]=e[0]+i.y;else if("A"===t)e[5]=e[5]+i.x,e[6]=e[6]+i.y;else for(var r=0,s=e.length;r<s;++r)e[r]=e[r]+(r%2?i.y:i.x);return b[t](e,i,n)}}(P[A].toUpperCase());w.PathArray=function(t,e){w.Array.call(this,t,e||[["M",0,0]])},w.PathArray.prototype=new w.Array,w.PathArray.prototype.constructor=w.PathArray,w.extend(w.PathArray,{toString:function(){return m(this.value)},move:function(t,e){var i=this.bbox();if(t-=i.x,e-=i.y,!isNaN(t)&&!isNaN(e))for(var n,r=this.value.length-1;r>=0;r--)n=this.value[r][0],"M"===n||"L"===n||"T"===n?(this.value[r][1]+=t,this.value[r][2]+=e):"H"===n?this.value[r][1]+=t:"V"===n?this.value[r][1]+=e:"C"===n||"S"===n||"Q"===n?(this.value[r][1]+=t,this.value[r][2]+=e,this.value[r][3]+=t,this.value[r][4]+=e,"C"===n&&(this.value[r][5]+=t,this.value[r][6]+=e)):"A"===n&&(this.value[r][6]+=t,this.value[r][7]+=e);return this},size:function(t,e){var i,n,r=this.bbox();for(i=this.value.length-1;i>=0;i--)n=this.value[i][0],"M"===n||"L"===n||"T"===n?(this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x,this.value[i][2]=(this.value[i][2]-r.y)*e/r.height+r.y):"H"===n?this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x:"V"===n?this.value[i][1]=(this.value[i][1]-r.y)*e/r.height+r.y:"C"===n||"S"===n||"Q"===n?(this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x,this.value[i][2]=(this.value[i][2]-r.y)*e/r.height+r.y,this.value[i][3]=(this.value[i][3]-r.x)*t/r.width+r.x,this.value[i][4]=(this.value[i][4]-r.y)*e/r.height+r.y,"C"===n&&(this.value[i][5]=(this.value[i][5]-r.x)*t/r.width+r.x,this.value[i][6]=(this.value[i][6]-r.y)*e/r.height+r.y)):"A"===n&&(this.value[i][1]=this.value[i][1]*t/r.width,this.value[i][2]=this.value[i][2]*e/r.height,this.value[i][6]=(this.value[i][6]-r.x)*t/r.width+r.x,this.value[i][7]=(this.value[i][7]-r.y)*e/r.height+r.y);return this},equalCommands:function(t){var e,i,n;for(t=new w.PathArray(t),n=this.value.length===t.value.length,e=0,i=this.value.length;n&&e<i;e++)n=this.value[e][0]===t.value[e][0];return n},morph:function(t){return t=new w.PathArray(t),this.equalCommands(t)?this.destination=t:this.destination=null,this},at:function(t){if(!this.destination)return this;var e,i,n,r,s=this.value,o=this.destination.value,a=[],h=new w.PathArray;for(e=0,i=s.length;e<i;e++){for(a[e]=[s[e][0]],n=1,r=s[e].length;n<r;n++)a[e][n]=s[e][n]+(o[e][n]-s[e][n])*t;"A"===a[e][0]&&(a[e][4]=+(0!==a[e][4]),a[e][5]=+(0!==a[e][5]))}return h.value=a,h},parse:function(t){if(t instanceof w.PathArray)return t.valueOf();var e,i={M:2,L:2,H:1,V:1,C:6,S:4,Q:4,T:2,A:7,Z:0};t="string"==typeof t?t.replace(w.regex.numbersWithDots,s).replace(w.regex.pathLetters," $& ").replace(w.regex.hyphen,"$1 -").trim().split(w.regex.delimiter):t.reduce(function(t,e){return[].concat.call(t,e)},[]);var n=[],r=new w.Point,o=new w.Point,a=0,h=t.length;do{w.regex.isPathLetter.test(t[a])?(e=t[a],++a):"M"===e?e="L":"m"===e&&(e="l"),n.push(b[e].call(null,t.slice(a,a+=i[e.toUpperCase()]).map(parseFloat),r,o))}while(h>a);return n},bbox:function(){return w.parser().path.setAttribute("d",this.toString()),w.parser.nodes.path.getBBox()}}),w.Number=w.invent({create:function(t,e){this.value=0,this.unit=e||"","number"==typeof t?this.value=isNaN(t)?0:isFinite(t)?t:t<0?-3.4e38:3.4e38:"string"==typeof t?(e=t.match(w.regex.numberAndUnit))&&(this.value=parseFloat(e[1]),"%"===e[5]?this.value/=100:"s"===e[5]&&(this.value*=1e3),this.unit=e[5]):t instanceof w.Number&&(this.value=t.valueOf(),this.unit=t.unit)},extend:{toString:function(){return("%"===this.unit?~~(1e8*this.value)/1e6:"s"===this.unit?this.value/1e3:this.value)+this.unit},toJSON:function(){return this.toString()},valueOf:function(){return this.value},plus:function(t){return t=new w.Number(t),new w.Number(this+t,this.unit||t.unit)},minus:function(t){return t=new w.Number(t),new w.Number(this-t,this.unit||t.unit)},times:function(t){return t=new w.Number(t),new w.Number(this*t,this.unit||t.unit)},divide:function(t){return t=new w.Number(t),new w.Number(this/t,this.unit||t.unit)},to:function(t){var e=new w.Number(this);return"string"==typeof t&&(e.unit=t),e},morph:function(t){return this.destination=new w.Number(t),t.relative&&(this.destination.value+=this.value),this},at:function(t){return this.destination?new w.Number(this.destination).minus(this).times(t).plus(this):this}}}),w.HtmlNode=w.invent({create:function(t){this.node=t},extend:{add:function(t,e){return t=i(t),t.node!==this.node.children[e]&&this.node.insertBefore(t.node,this.node.children[e]||null),this},put:function(t,e){return this.add(t,e),t}}}),w.Element=w.invent({create:function(t){this.events={},this.dom={},this.node=t,this.node&&(this.type=t.nodeName,this.node.instance=this,this.events=t.events||{},t.hasAttribute("svgjs:data")&&this.setData(JSON.parse(t.getAttribute("svgjs:data"))||{}))},extend:{x:function(t){return this.attr("x",t)},y:function(t){return this.attr("y",t)},cx:function(t){return null==t?this.x()+this.width()/2:this.x(t-this.width()/2)},cy:function(t){return null==t?this.y()+this.height()/2:this.y(t-this.height()/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},width:function(t){return this.attr("width",t)},height:function(t){return this.attr("height",t)},size:function(t,e){var i=d(this,t,e);return this.width(new w.Number(i.width)).height(new w.Number(i.height))},clone:function(t){this.writeDataToDom();var e=v(this.node.cloneNode(!0));return t?t.add(e):this.after(e),e},remove:function(){return this.parent()&&this.parent().removeElement(this),this},replace:function(t){return this.after(t).remove(),t},addTo:function(t){return i(t).put(this)},putIn:function(t){return i(t).add(this)},id:function(t){return void 0!==t||this.node.id||(this.node.id=w.eid(this.type)),this.attr("id",t)},inside:function(t,e){var i=this.bbox();return t>i.x&&e>i.y&&t<i.x+i.width&&e<i.y+i.height},show:function(){return this.css("display","")},hide:function(){return this.css("display","none")},visible:function(){return"none"!==this.css("display")},toString:function(){return this.id()},classes:function(){var t=this.attr("class");return null==t?[]:t.trim().split(w.regex.delimiter)},hasClass:function(t){return-1!==this.classes().indexOf(t)},addClass:function(t){if(!this.hasClass(t)){var e=this.classes();e.push(t),this.attr("class",e.join(" "))}return this},removeClass:function(t){return this.hasClass(t)&&this.attr("class",this.classes().filter(function(e){return e!==t}).join(" ")),this},toggleClass:function(t){return this.hasClass(t)?this.removeClass(t):this.addClass(t)},reference:function(t){return w.get(this.attr(t))},parent:function(e){var i=this;if(!i.node.parentNode)return null;if(i=w.adopt(i.node.parentNode),!e)return i;for(;i&&i.node instanceof t.SVGElement;){if("string"==typeof e?i.matches(e):i instanceof e)return i;i=w.adopt(i.node.parentNode)}},doc:function(){var t=this.parent(w.Doc);return t&&t.doc()},defs:function(){return this.doc().defs()},parents:function(t){var e=[],i=this;do{if(!(i=i.parent(t))||!i.node)break;e.push(i)}while(i.parent);return e},matches:function(t){return h(this.node,t)},native:function(){return this.node},svg:function(t){var i,n;if(!(t&&this instanceof w.Parent))return this.writeDataToDom(),this.node.outerHTML;for(i=e.createElementNS(w.ns,"svg"),i.innerHTML=t,n=i.children.length;n--;)this.node.appendChild(i.firstElementChild);return this},writeDataToDom:function(){return this.is(w.Parent)&&this.each(function(){this.writeDataToDom()}),this.node.removeAttribute("svgjs:data"),Object.keys(this.dom).length&&this.node.setAttribute("svgjs:data",JSON.stringify(this.dom)),this},setData:function(t){return this.dom=t,this},is:function(t){return a(this,t)}}}),w.easing={"-":function(t){return t},"<>":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)}},w.morph=function(t){return function(e,i){return new w.MorphObj(e,i).at(t)}},w.Situation=w.invent({create:function(t){this.init=!1,this.reversed=!1,this.reversing=!1,this.duration=new w.Number(t.duration).valueOf(),this.delay=new w.Number(t.delay).valueOf(),this.start=+new Date+this.delay,this.finish=this.start+this.duration,this.ease=t.ease,this.loop=0,this.loops=!1,this.animations={},this.attrs={},this.styles={},this.transforms=[],this.once={}}}),w.Timeline=w.invent({create:function(t){this._target=t,this.situations=[],this.active=!1,this.situation=null,this.paused=!1,this.lastPos=0,this.pos=0,this.absPos=0,this._speed=1},extend:{animate:function(t,e,i){"object"==typeof t&&(e=t.ease,i=t.delay,t=t.duration);var n=new w.Situation({duration:t||1e3,delay:i||0,ease:w.easing[e||"-"]||e});return this.queue(n),this},delay:function(t){var e=new w.Situation({duration:t,delay:0,ease:w.easing["-"]});return this.queue(e)},target:function(t){return t&&t instanceof w.Element?(this._target=t,this):this._target},timeToAbsPos:function(t){return(t-this.situation.start)/(this.situation.duration/this._speed)},absPosToTime:function(t){return this.situation.duration/this._speed*t+this.situation.start},startAnimFrame:function(){this.stopAnimFrame(),this.animationFrame=t.requestAnimationFrame(function(){this.step()}.bind(this))},stopAnimFrame:function(){t.cancelAnimationFrame(this.animationFrame)},start:function(){return!this.active&&this.situation&&(this.active=!0,this.startCurrent()),this},startCurrent:function(){return this.situation.start=+new Date+this.situation.delay/this._speed,this.situation.finish=this.situation.start+this.situation.duration/this._speed,this.initAnimations().step()},queue:function(t){return("function"==typeof t||t instanceof w.Situation)&&this.situations.push(t),this.situation||(this.situation=this.situations.shift()),this},dequeue:function(){return this.stop(),this.situation=this.situations.shift(),this.situation&&(this.situation instanceof w.Situation?this.start():this.situation(this)),this},initAnimations:function(){var t,e,i,n=this.situation;if(n.init)return this;for(t in n.animations)for(i=this.target()[t](),Array.isArray(i)||(i=[i]),Array.isArray(n.animations[t])||(n.animations[t]=[n.animations[t]]),e=i.length;e--;)n.animations[t][e]instanceof w.Number&&(i[e]=new w.Number(i[e])),n.animations[t][e]=i[e].morph(n.animations[t][e]);for(t in n.attrs)n.attrs[t]=new w.MorphObj(this.target().attr(t),n.attrs[t]);for(t in n.styles)n.styles[t]=new w.MorphObj(this.target().css(t),n.styles[t]);return n.initialTransformation=this.target().matrixify(),n.init=!0,this},clearQueue:function(){return this.situations=[],this},clearCurrent:function(){return this.situation=null,this},stop:function(t,e){var i=this.active;return this.active=!1,e&&this.clearQueue(),t&&this.situation&&(!i&&this.startCurrent(),this.atEnd()),this.stopAnimFrame(),this.clearCurrent()},reset:function(){if(this.situation){var t=this.situation;this.stop(),this.situation=t,this.atStart()}return this},finish:function(){for(this.stop(!0,!1);this.dequeue().situation&&this.stop(!0,!1););return this.clearQueue().clearCurrent(),this},atStart:function(){return this.at(0,!0)},atEnd:function(){return!0===this.situation.loops&&(this.situation.loops=this.situation.loop+1),"number"==typeof this.situation.loops?this.at(this.situation.loops,!0):this.at(1,!0)},at:function(t,e){var i=this.situation.duration/this._speed;return this.absPos=t,e||(this.situation.reversed&&(this.absPos=1-this.absPos),this.absPos+=this.situation.loop),this.situation.start=+new Date-this.absPos*i,this.situation.finish=this.situation.start+i,this.step(!0)},speed:function(t){return 0===t?this.pause():t?(this._speed=t,this.at(this.absPos,!0)):this._speed},loop:function(t,e){var i=this.last();return i.loops=null==t||t,i.loop=0,e&&(i.reversing=!0),this},pause:function(){return this.paused=!0,this.stopAnimFrame(),this},play:function(){return this.paused?(this.paused=!1,this.at(this.absPos,!0)):this},reverse:function(t){var e=this.last();return e.reversed=void 0===t?!e.reversed:t,this},progress:function(t){return t?this.situation.ease(this.pos):this.pos},after:function(t){function e(n){n.detail.situation===i&&(t.call(this,i),this.off("finished.fx",e))}var i=this.last();return this.target().on("finished.fx",e),this._callStart()},during:function(t){function e(e){e.detail.situation===i&&t.call(this,e.detail.pos,w.morph(e.detail.pos),e.detail.eased,i)}var i=this.last();return this.target().off("during.fx",e).on("during.fx",e),this.after(function(){this.off("during.fx",e)}),this._callStart()},afterAll:function(t){var e=function e(i){t.call(this),this.off("allfinished.fx",e)};return this.target().off("allfinished.fx",e).on("allfinished.fx",e),this._callStart()},duringAll:function(t){var e=function(e){t.call(this,e.detail.pos,w.morph(e.detail.pos),e.detail.eased,e.detail.situation)};return this.target().off("during.fx",e).on("during.fx",e),this.afterAll(function(){this.off("during.fx",e)}),this._callStart()},last:function(){return this.situations.length?this.situations[this.situations.length-1]:this.situation},add:function(t,e,i){return this.last()[i||"animations"][t]=e,this._callStart()},step:function(t){if(t||(this.absPos=this.timeToAbsPos(+new Date)),!1!==this.situation.loops){var e,i,n;e=Math.max(this.absPos,0),i=Math.floor(e),!0===this.situation.loops||i<this.situation.loops?(this.pos=e-i,n=this.situation.loop,this.situation.loop=i):(this.absPos=this.situation.loops,this.pos=1,n=this.situation.loop-1,this.situation.loop=this.situation.loops),this.situation.reversing&&(this.situation.reversed=this.situation.reversed!==Boolean((this.situation.loop-n)%2))}else this.absPos=Math.min(this.absPos,1),this.pos=this.absPos;this.pos<0&&(this.pos=0),this.situation.reversed&&(this.pos=1-this.pos);var r=this.situation.ease(this.pos);for(var s in this.situation.once)s>this.lastPos&&s<=r&&(this.situation.once[s].call(this.target(),this.pos,r),delete this.situation.once[s]);return this.active&&this.target().fire("during",{pos:this.pos,eased:r,fx:this,situation:this.situation}),this.situation?(this.eachAt(),1===this.pos&&!this.situation.reversed||this.situation.reversed&&0===this.pos?(this.stopAnimFrame(),this.target().fire("finished",{fx:this,situation:this.situation}),this.situations.length||(this.target().fire("allfinished"),this.situations.length||(this.target().off(".fx"),this.active=!1)),this.active?this.dequeue():this.clearCurrent()):!this.paused&&this.active&&this.startAnimFrame(),this.lastPos=r,this):this},eachAt:function(){var t,e,i=this,n=this.target(),r=this.situation;for(t in r.animations)e=[].concat(r.animations[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(i.pos),i.pos):t}),n[t].apply(n,e);for(t in r.attrs)e=[t].concat(r.attrs[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(i.pos),i.pos):t}),n.attr.apply(n,e);for(t in r.styles)e=[t].concat(r.styles[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(i.pos),i.pos):t}),n.css.apply(n,e);return r.transforms.length,this},once:function(t,e,i){var n=this.last();return i||(t=n.ease(t)),n.once[t]=e,this},_callStart:function(){return setTimeout(function(){this.start()}.bind(this),0),this}},parent:w.Element,construct:{animate:function(t,e,i){return(this.fx||(this.fx=new w.Timeline(this))).animate(t,e,i)},delay:function(t){return(this.fx||(this.fx=new w.Timeline(this))).delay(t)},stop:function(t,e){return this.fx&&this.fx.stop(t,e),this},finish:function(){return this.fx&&this.fx.finish(),this},pause:function(){return this.fx&&this.fx.pause(),this},play:function(){return this.fx&&this.fx.play(),this},speed:function(t){if(this.fx){if(null==t)return this.fx.speed();this.fx.speed(t)}return this}}}),w.MorphObj=w.invent({create:function(t,e){return w.Color.isColor(e)?new w.Color(t).morph(e):w.regex.delimiter.test(t)?new w.Array(t).morph(e):w.regex.numberAndUnit.test(e)?new w.Number(t).morph(e):(this.value=t,void(this.destination=e))},extend:{at:function(t,e){return e<1?this.value:this.destination},valueOf:function(){return this.value}}}),w.extend(w.Timeline,{attr:function(t,e,i){if("object"==typeof t)for(var n in t)this.attr(n,t[n]);else this.add(t,e,"attrs");return this},css:function(t,e){if("object"==typeof t)for(var i in t)this.css(i,t[i]);else this.add(t,e,"styles");return this},x:function(t,e){if(this.target()instanceof w.G)return this.transform({x:t},e),this;var i=new w.Number(t);return i.relative=e,this.add("x",i)},y:function(t,e){if(this.target()instanceof w.G)return this.transform({y:t},e),this;var i=new w.Number(t);return i.relative=e,this.add("y",i)},cx:function(t){return this.add("cx",new w.Number(t))},cy:function(t){return this.add("cy",new w.Number(t))},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},size:function(t,e){if(this.target()instanceof w.Text)this.attr("font-size",t);else{var i;t&&e||(i=this.target().bbox()),t||(t=i.width/i.height*e),e||(e=i.height/i.width*t),this.add("width",new w.Number(t)).add("height",new w.Number(e))}return this},width:function(t){return this.add("width",new w.Number(t))},height:function(t){return this.add("height",new w.Number(t))},plot:function(t,e,i,n){return 4===arguments.length?this.plot([t,e,i,n]):this.add("plot",new(this.target().MorphArray)(t))},leading:function(t){return this.target().leading?this.add("leading",new w.Number(t)):this},viewbox:function(t,e,i,n){return this.target()instanceof w.Container&&this.add("viewbox",new w.Box(t,e,i,n)),this},update:function(t){if(this.target()instanceof w.Stop){if("number"==typeof t||t instanceof w.Number)return this.update({offset:arguments[0],color:arguments[1],opacity:arguments[2]});null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",t.offset)}return this}}),w.Matrix=w.invent({create:function(t){var e,i=p([1,0,0,1,0,0]);for(t=t instanceof w.Element?t.matrixify():"string"==typeof t?p(t.split(w.regex.delimiter).map(parseFloat)):Array.isArray(t)?p(t):"object"==typeof t?t:6===arguments.length?p([].slice.call(arguments)):i,e=N.length-1;e>=0;--e)this[N[e]]=null!=t[N[e]]?t[N[e]]:i[N[e]]},extend:{clone:function(){return new w.Matrix(this)},transform:function(t){if(null!=t.a){var e=new w.Matrix(t);return this.lmultiply(e)}var i=!t.flip||"x"!==t.flip&&"both"!==t.flip?1:-1,n=!t.flip||"y"!==t.flip&&"both"!==t.flip?1:-1,r=t.skew&&t.skew.length?t.skew[0]:isFinite(t.skew)?t.skew:isFinite(t.skewX)?t.skewX:0,s=t.skew&&t.skew.length?t.skew[1]:isFinite(t.skew)?t.skew:isFinite(t.skewY)?t.skewY:0,o=t.scale&&t.scale.length?t.scale[0]*i:isFinite(t.scale)?t.scale*i:isFinite(t.scaleX)?t.scaleX*i:i,a=t.scale&&t.scale.length?t.scale[1]*n:isFinite(t.scale)?t.scale*n:isFinite(t.scaleY)?t.scaleY*n:n,h=t.shear||0,u=t.rotate||0,l=new w.Point(null==t.ox?t.origin:t.ox,t.oy),c=l.x,f=l.y,d=new w.Point(null==t.px?t.position:t.px,t.py,{x:null,y:null}),p=d.x,m=d.y,v=new w.Point(null==t.tx?t.translate:t.tx,t.ty),x=v.x,y=v.y,g=new w.Point(null==t.rx?t.relative:t.rx,t.ry),b=g.x,P=g.y,A=new w.Matrix(this),C=(new w.Matrix).translate(-c,-f).scale(o,a).skew(r,s).shear(h).rotate(u).translate(c,f).translate(b,P).lmultiply(A);if(isFinite(p)||isFinite(m)){var N=new w.Point(c-b,f-P).transform(C),M=p?p-N.x:0,S=m?m-N.y:0;C=C.translate(M,S)}return C=C.translate(x,y)},compose:function(t){var e=t.scaleX||1,i=t.scaleY||1,n=t.shear||0,r=t.rotate||0,s=t.translateX||0,o=t.translateY||0;return(new w.Matrix).scale(e,i).shear(n).rotate(r).translate(s,o).lmultiply(this)},decompose:function(){var t=this.a,e=this.b,i=this.c,n=this.d,r=this.e,s=this.f,o=t*n-e*i,a=o>0?1:-1,h=a*Math.sqrt(t*t+e*e),u=180/Math.PI*Math.atan2(a*e,a*t),l=(t*i+e*n)/o;return{scaleX:h,scaleY:i*h/(l*t-e)||n*h/(l*e+t),shear:l,rotate:u,translateX:r,translateY:s,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f}},morph:function(t){return this.destination=new w.Matrix(t),this},at:function(t){return this.destination?new w.Matrix({a:this.a+(this.destination.a-this.a)*t,b:this.b+(this.destination.b-this.b)*t,c:this.c+(this.destination.c-this.c)*t,d:this.d+(this.destination.d-this.d)*t,e:this.e+(this.destination.e-this.e)*t,f:this.f+(this.destination.f-this.f)*t}):this},multiply:function(t){var e=this,i=new w.Matrix(t),n=e.a*i.a+e.c*i.b,r=e.b*i.a+e.d*i.b,s=e.a*i.c+e.c*i.d,o=e.b*i.c+e.d*i.d,a=e.e+e.a*i.e+e.c*i.f,h=e.f+e.b*i.e+e.d*i.f;return new w.Matrix(n,r,s,o,a,h)},lmultiply:function(t){return new w.Matrix(t).multiply(this)},inverse:function(){return new w.Matrix(this.native().inverse())},translate:function(t,e){var i=new w.Matrix(this);return i.e+=t||0,i.f+=e||0,i},scale:function(t,e,i,n){1===arguments.length?e=t:3===arguments.length&&(n=i,i=e,e=t);var r=new w.Matrix(t,0,0,e,0,0);return this.around(i,n,r)},rotate:function(t,e,i){t=w.utils.radians(t);var n=new w.Matrix(Math.cos(t),Math.sin(t),-Math.sin(t),Math.cos(t),0,0);return this.around(e,i,n)},flip:function(t,e){return"x"===t?this.scale(-1,1,e,0):"y"===t?this.scale(1,-1,0,e):this.scale(-1,-1,t,e||t)},shear:function(t,e,i){var n=new w.Matrix(1,0,t,1,0,0);return this.around(e,i,n)},skew:function(t,e,i,n){1===arguments.length?e=t:3===arguments.length&&(n=i,i=e,e=t),t=w.utils.radians(t),e=w.utils.radians(e)
+;var r=new w.Matrix(1,Math.tan(e),Math.tan(t),1,0,0);return this.around(i,n,r)},skewX:function(t,e,i){return this.skew(t,0,e,i)},skewY:function(t,e,i){return this.skew(0,t,e,i)},around:function(t,e,i){var n=t||0,r=e||0;return this.translate(-n,-r).lmultiply(i).translate(n,r)},native:function(){for(var t=w.parser.nodes.svg.node.createSVGMatrix(),e=N.length-1;e>=0;e--)t[N[e]]=this[N[e]];return t},equals:function(t){var e=new w.Matrix(t);return g(this.a,e.a)&&g(this.b,e.b)&&g(this.c,e.c)&&g(this.d,e.d)&&g(this.e,e.e)&&g(this.f,e.f)},toString:function(){return"matrix("+this.a+","+this.b+","+this.c+","+this.d+","+this.e+","+this.f+")"}},parent:w.Element,construct:{ctm:function(){return new w.Matrix(this.node.getCTM())},screenCTM:function(){if(this instanceof w.Doc&&!this.isRoot()){var t=this.rect(1,1),e=t.node.getScreenCTM();return t.remove(),new w.Matrix(e)}return new w.Matrix(this.node.getScreenCTM())}}}),w.Point=w.invent({create:function(t,e,i){var n;i=i||{x:0,y:0},n=Array.isArray(t)?{x:t[0],y:t[1]}:"object"==typeof t?{x:t.x,y:t.y}:{x:t,y:e},this.x=null==n.x?i.x:n.x,this.y=null==n.y?i.y:n.y},extend:{clone:function(){return new w.Point(this)},morph:function(t,e){return this.destination=new w.Point(t,e),this},at:function(t){return this.destination?new w.Point({x:this.x+(this.destination.x-this.x)*t,y:this.y+(this.destination.y-this.y)*t}):this},native:function(){var t=w.parser.nodes.svg.node.createSVGPoint();return t.x=this.x,t.y=this.y,t},transform:function(t){return new w.Point(this.native().matrixTransform(t.native()))}}}),w.extend(w.Element,{point:function(t,e){return new w.Point(t,e).transform(this.screenCTM().inverse())}}),w.extend(w.Element,{attr:function(t,e,i){if(null==t){for(t={},e=this.node.attributes,i=e.length-1;i>=0;i--)t[e[i].nodeName]=w.regex.isNumber.test(e[i].nodeValue)?parseFloat(e[i].nodeValue):e[i].nodeValue;return t}if("object"==typeof t)for(e in t)this.attr(e,t[e]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return e=this.node.getAttribute(t),null==e?w.defaults.attrs[t]:w.regex.isNumber.test(e)?parseFloat(e):e;"fill"!==t&&"stroke"!==t||(w.regex.isImage.test(e)&&(e=this.doc().defs().image(e)),e instanceof w.Image&&(e=this.doc().defs().pattern(0,0,function(){this.add(e)}))),"number"==typeof e?e=new w.Number(e):w.Color.isColor(e)?e=new w.Color(e):Array.isArray(e)&&(e=new w.Array(e)),"leading"===t?this.leading&&this.leading(e):"string"==typeof i?this.node.setAttributeNS(i,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!==t&&"x"!==t||this.rebuild(t,e)}return this}}),w.extend(w.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){return(this.attr("transform")||"").split(w.regex.transforms).slice(0,-1).map(function(t){var e=t.trim().split("(");return[e[0],e[1].split(w.regex.delimiter).map(function(t){return parseFloat(t)})]}).reverse().reduce(function(t,e){return"matrix"===e[0]?t.lmultiply(p(e[1])):t[e[0]].apply(t,e[1])},new w.Matrix)},toParent:function(t){if(this===t)return this;var e=this.screenCTM(),i=t.screenCTM().inverse();return this.addTo(t).untransform().transform(i.multiply(e)),this},toDoc:function(){return this.toParent(this.doc())}}),w.extend(w.Element,{transform:function(t,e){var i=this.bbox();if(null==t||"string"==typeof t){var n=new w.Matrix(this).decompose();return n[t]||n}if("string"==typeof t.origin||null==t.origin&&null==t.ox&&null==t.oy){var r="string"==typeof t.origin?t.origin.toLowerCase().trim():"center",s=i.height,o=i.width,a=i.x,h=i.y;t.ox=r.includes("left")?a:r.includes("right")?a+o:a+o/2,t.oy=r.includes("top")?h:r.includes("bottom")?h+s:h+s/2,t.origin=null}var u=!0===e?this:e||!1,l=new w.Matrix(u).transform(t);return this.attr("transform",l)}}),w.extend(w.Timeline,{transform:function(t,e,i){}}),w.extend(w.Element,{css:function(t,e){var i,n,r={};if(0===arguments.length)return this.node.style.cssText.split(/\s*;\s*/).filter(function(t){return!!t.length}).forEach(function(t){i=t.split(/\s*:\s*/),r[i[0]]=i[1]}),r;if(arguments.length<2){if(Array.isArray(t)){for(n=t.length;n--;)r[u(t[n])]=this.node.style[u(t[n])];return r}if("string"==typeof t)return this.node.style[u(t)];if("object"==typeof t)for(n in t)this.node.style[u(n)]=null==t[n]||w.regex.isBlank.test(t[n])?"":t[n]}return 2===arguments.length&&(this.node.style[u(t)]=null==e||w.regex.isBlank.test(e)?"":e),this}}),w.Parent=w.invent({create:function(t){this.constructor(t)},inherit:w.Element,extend:{children:function(){return w.utils.map(this.node.children,function(t){return w.adopt(t)})},add:function(t,e){return t=i(t),t.node!==this.node.children[e]&&this.node.insertBefore(t.node,this.node.children[e]||null),this},put:function(t,e){return this.add(t,e),t.instance||t},has:function(t){return this.index(t)>=0},index:function(t){return[].slice.call(this.node.children).indexOf(t.node)},get:function(t){return w.adopt(this.node.children[t])},first:function(){return this.get(0)},last:function(){return this.get(this.node.children.length-1)},each:function(t,e){var i,n,r=this.children();for(i=0,n=r.length;i<n;i++)r[i]instanceof w.Element&&t.apply(r[i],[i,r]),e&&r[i]instanceof w.Parent&&r[i].each(t,e);return this},removeElement:function(t){return this.node.removeChild(t.node),this},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return delete this._defs,this}}}),w.extend(w.Parent,{flatten:function(t){return this instanceof w.G||this instanceof w.Doc?(t=t||(this instanceof w.Doc&&this.isRoot()?this:this.parent(w.Parent)),this.each(function(){return this instanceof w.Defs?this:this instanceof w.Parent?this.flatten(t):this.toParent(t)}),this.node.firstElementChild||this.remove(),this):this},ungroup:function(t){return this instanceof w.G||this instanceof w.Doc&&!this.isRoot()?(t=t||this.parent(w.Parent),this.each(function(){return this.toParent(t)}),this.remove(),this):this}}),w.Container=w.invent({create:function(t){this.constructor(t)},inherit:w.Parent}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","mouseenter","mouseleave","touchstart","touchmove","touchleave","touchend","touchcancel"].forEach(function(t){w.Element.prototype[t]=function(e){return w.on(this,t,e),this}}),w.listenerId=0,w.on=function(t,e,i,n,r){var s=i.bind(n||t),o=t instanceof w.Element?t.node:t;o.instance=o.instance||{events:{}};var a=o.instance.events;i._svgjsListenerId||(i._svgjsListenerId=++w.listenerId),e.split(w.regex.delimiter).forEach(function(t){var e=t.split(".")[0],n=t.split(".")[1]||"*";a[e]=a[e]||{},a[e][n]=a[e][n]||{},a[e][n][i._svgjsListenerId]=s,o.addEventListener(e,s,r||!1)})},w.off=function(t,e,i,n){var r=t instanceof w.Element?t.node:t;if(r.instance&&("function"!=typeof i||(i=i._svgjsListenerId))){var s=r.instance.events;(e||"").split(w.regex.delimiter).forEach(function(t){var e,o,a=t&&t.split(".")[0],h=t&&t.split(".")[1];if(i)s[a]&&s[a][h||"*"]&&(r.removeEventListener(a,s[a][h||"*"][i],n||!1),delete s[a][h||"*"][i]);else if(a&&h){if(s[a]&&s[a][h]){for(o in s[a][h])w.off(r,[a,h].join("."),o);delete s[a][h]}}else if(h)for(t in s)for(e in s[t])h===e&&w.off(r,[t,h].join("."));else if(a){if(s[a]){for(e in s[a])w.off(r,[a,e].join("."));delete s[a]}}else{for(t in s)w.off(r,t);r.instance.events={}}})}},w.extend(w.Element,{on:function(t,e,i,n){return w.on(this,t,e,i,n),this},off:function(t,e){return w.off(this.node,t,e),this},dispatch:function(e,i){return e instanceof t.Event?this.node.dispatchEvent(e):this.node.dispatchEvent(e=new t.CustomEvent(e,{detail:i,cancelable:!0})),e},fire:function(t,e){return this.dispatch(t,e),this}}),w.Defs=w.invent({create:"defs",inherit:w.Container}),w.G=w.invent({create:"g",inherit:w.Container,extend:{},construct:{group:function(){return this.put(new w.G)}}}),w.extend(w.Element,{siblings:function(){return this.parent().children()},position:function(){return this.parent().index(this)},next:function(){return this.siblings()[this.position()+1]},prev:function(){return this.siblings()[this.position()-1]},forward:function(){var t=this.position()+1,e=this.parent();return e.removeElement(this).add(this,t),e instanceof w.Doc&&e.node.appendChild(e.defs().node),this},backward:function(){var t=this.position();return t>0&&this.parent().removeElement(this).add(this,t-1),this},front:function(){var t=this.parent();return t.node.appendChild(this.node),t instanceof w.Doc&&t.node.appendChild(t.defs().node),this},back:function(){return this.position()>0&&this.parent().removeElement(this).add(this,0),this},before:function(t){t.remove();var e=this.position();return this.parent().add(t,e),this},after:function(t){t.remove();var e=this.position();return this.parent().add(t,e+1),this}}),w.Mask=w.invent({create:"mask",inherit:w.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unmask()}),w.Element.prototype.remove.call(this)},targets:function(){return w.select('svg [mask*="'+this.id()+'"]')}},construct:{mask:function(){return this.defs().put(new w.Mask)}}}),w.extend(w.Element,{maskWith:function(t){var e=t instanceof w.Mask?t:this.parent().mask().add(t);return this.attr("mask",'url("#'+e.id()+'")')},unmask:function(){return this.attr("mask",null)},masker:function(){return this.reference("mask")}}),w.ClipPath=w.invent({create:"clipPath",inherit:w.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unclip()}),w.Element.prototype.remove.call(this)},targets:function(){return w.select('svg [clip-path*="'+this.id()+'"]')}},construct:{clip:function(){return this.defs().put(new w.ClipPath)}}}),w.extend(w.Element,{clipWith:function(t){var e=t instanceof w.ClipPath?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.id()+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}),w.Gradient=w.invent({create:function(t){this.constructor("object"==typeof t?t:w.create(t+"Gradient"))},inherit:w.Container,extend:{stop:function(t,e,i){return this.put(new w.Stop).update(t,e,i)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},url:function(){return"url(#"+this.id()+")"},toString:function(){return this.url()},attr:function(t,e,i){return"transform"===t&&(t="gradientTransform"),w.Container.prototype.attr.call(this,t,e,i)}},construct:{gradient:function(t,e){return this.defs().gradient(t,e)}}}),w.extend([w.Gradient,w.Timeline],{from:function(t,e){return"radialGradient"===(this._target||this).type?this.attr({fx:new w.Number(t),fy:new w.Number(e)}):this.attr({x1:new w.Number(t),y1:new w.Number(e)})},to:function(t,e){return"radialGradient"===(this._target||this).type?this.attr({cx:new w.Number(t),cy:new w.Number(e)}):this.attr({x2:new w.Number(t),y2:new w.Number(e)})}}),w.extend(w.Defs,{gradient:function(t,e){return this.put(new w.Gradient(t)).update(e)}}),w.Stop=w.invent({create:"stop",inherit:w.Element,extend:{update:function(t){return("number"==typeof t||t instanceof w.Number)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new w.Number(t.offset)),this}}}),w.Pattern=w.invent({create:"pattern",inherit:w.Container,extend:{url:function(){return"url(#"+this.id()+")"},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return this.url()},attr:function(t,e,i){return"transform"===t&&(t="patternTransform"),w.Container.prototype.attr.call(this,t,e,i)}},construct:{pattern:function(t,e,i){return this.defs().pattern(t,e,i)}}}),w.extend(w.Defs,{pattern:function(t,e,i){return this.put(new w.Pattern).update(i).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}),w.Doc=w.invent({create:function(t){this.constructor(t||w.create("svg")),this.namespace()},inherit:w.Container,extend:{isRoot:function(){return!(this.node.parentNode&&this.node.parentNode instanceof t.SVGElement&&"#document"!==this.node.parentNode.nodeName)},doc:function(){return this.isRoot()?this:w.Element.prototype.doc.call(this)},namespace:function(){return this.isRoot()?this.attr({xmlns:w.ns,version:"1.1"}).attr("xmlns:xlink",w.xlink,w.xmlns).attr("xmlns:svgjs",w.svgjs,w.xmlns):this.doc().namespace()},defs:function(){return this.isRoot()?w.adopt(this.node.getElementsByTagName("defs")[0])||this.put(new w.Defs):this.doc().defs()},parent:function(t){return this.isRoot()?"#document"===this.node.parentNode.nodeName?null:this.node.parentNode:w.Element.prototype.parent.call(this,t)},remove:function(){return this.isRoot()?(this.parent()&&this.parent().removeChild(this.node),this):w.Element.prototype.remove.call(this)},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this}},construct:{nested:function(){return this.put(new w.Doc)}}}),w.Shape=w.invent({create:function(t){this.constructor(t)},inherit:w.Element}),w.Bare=w.invent({create:function(t,e){if(this.constructor(w.create(t)),e)for(var i in e.prototype)"function"==typeof e.prototype[i]&&(this[i]=e.prototype[i])},inherit:w.Element,extend:{words:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(e.createTextNode(t)),this}}}),w.extend(w.Parent,{element:function(t,e){return this.put(new w.Bare(t,e))}}),w.Symbol=w.invent({create:"symbol",inherit:w.Container,construct:{symbol:function(){return this.put(new w.Symbol)}}}),w.Use=w.invent({create:"use",inherit:w.Shape,extend:{element:function(t,e){return this.attr("href",(e||"")+"#"+t,w.xlink)}},construct:{use:function(t,e){return this.put(new w.Use).element(t,e)}}}),w.Rect=w.invent({create:"rect",inherit:w.Shape,construct:{rect:function(t,e){return this.put(new w.Rect).size(t,e)}}}),w.Circle=w.invent({create:"circle",inherit:w.Shape,construct:{circle:function(t){return this.put(new w.Circle).rx(new w.Number(t).divide(2)).move(0,0)}}}),w.extend([w.Circle,w.Timeline],{rx:function(t){return this.attr("r",t)},ry:function(t){return this.rx(t)}}),w.Ellipse=w.invent({create:"ellipse",inherit:w.Shape,construct:{ellipse:function(t,e){return this.put(new w.Ellipse).size(t,e).move(0,0)}}}),w.extend([w.Ellipse,w.Rect,w.Timeline],{rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)}}),w.extend([w.Circle,w.Ellipse],{x:function(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())},y:function(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())},cx:function(t){return null==t?this.attr("cx"):this.attr("cx",t)},cy:function(t){return null==t?this.attr("cy"):this.attr("cy",t)},width:function(t){return null==t?2*this.rx():this.rx(new w.Number(t).divide(2))},height:function(t){return null==t?2*this.ry():this.ry(new w.Number(t).divide(2))},size:function(t,e){var i=d(this,t,e);return this.rx(new w.Number(i.width).divide(2)).ry(new w.Number(i.height).divide(2))}}),w.Line=w.invent({create:"line",inherit:w.Shape,extend:{array:function(){return new w.PointArray([[this.attr("x1"),this.attr("y1")],[this.attr("x2"),this.attr("y2")]])},plot:function(t,e,i,n){return null==t?this.array():(t=void 0!==e?{x1:t,y1:e,x2:i,y2:n}:new w.PointArray(t).toLine(),this.attr(t))},move:function(t,e){return this.attr(this.array().move(t,e).toLine())},size:function(t,e){var i=d(this,t,e);return this.attr(this.array().size(i.width,i.height).toLine())}},construct:{line:function(t,e,i,n){return w.Line.prototype.plot.apply(this.put(new w.Line),null!=t?[t,e,i,n]:[0,0,0,0])}}}),w.Polyline=w.invent({create:"polyline",inherit:w.Shape,construct:{polyline:function(t){return this.put(new w.Polyline).plot(t||new w.PointArray)}}}),w.Polygon=w.invent({create:"polygon",inherit:w.Shape,construct:{polygon:function(t){return this.put(new w.Polygon).plot(t||new w.PointArray)}}}),w.extend([w.Polyline,w.Polygon],{array:function(){return this._array||(this._array=new w.PointArray(this.attr("points")))},plot:function(t){return null==t?this.array():this.clear().attr("points","string"==typeof t?t:this._array=new w.PointArray(t))},clear:function(){return delete this._array,this},move:function(t,e){return this.attr("points",this.array().move(t,e))},size:function(t,e){var i=d(this,t,e);return this.attr("points",this.array().size(i.width,i.height))}}),w.extend([w.Line,w.Polyline,w.Polygon],{MorphArray:w.PointArray,x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},width:function(t){var e=this.bbox();return null==t?e.width:this.size(t,e.height)},height:function(t){var e=this.bbox();return null==t?e.height:this.size(e.width,t)}}),w.Path=w.invent({create:"path",inherit:w.Shape,extend:{MorphArray:w.PathArray,array:function(){return this._array||(this._array=new w.PathArray(this.attr("d")))},plot:function(t){return null==t?this.array():this.clear().attr("d","string"==typeof t?t:this._array=new w.PathArray(t))},clear:function(){return delete this._array,this},move:function(t,e){return this.attr("d",this.array().move(t,e))},x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},size:function(t,e){var i=d(this,t,e);return this.attr("d",this.array().size(i.width,i.height))},width:function(t){return null==t?this.bbox().width:this.size(t,this.bbox().height)},height:function(t){return null==t?this.bbox().height:this.size(this.bbox().width,t)}},construct:{path:function(t){return this.put(new w.Path).plot(t||new w.PathArray)}}}),w.Image=w.invent({create:"image",inherit:w.Shape,extend:{load:function(e,i){if(!e)return this;var n=new t.Image;return w.on(n,"load",function(t){var r=this.parent(w.Pattern);0===this.width()&&0===this.height()&&this.size(n.width,n.height),r instanceof w.Pattern&&0===r.width()&&0===r.height()&&r.size(this.width(),this.height()),"function"==typeof i&&i.call(this,{width:n.width,height:n.height,ratio:n.width/n.height,url:e})},this),w.on(n,"load error",function(){w.off(n)}),this.attr("href",n.src=e,w.xlink)}},construct:{image:function(t,e){return this.put(new w.Image).size(0,0).load(t,e)}}}),w.Text=w.invent({create:function(t){this.constructor(t||w.create("text")),this.dom.leading=new w.Number(1.3),this._rebuild=!0,this._build=!1,this.attr("font-family",w.defaults.attrs["font-family"])},inherit:w.Parent,extend:{x:function(t){return null==t?this.attr("x"):this.attr("x",t)},y:function(t){var e=this.attr("y"),i="number"==typeof e?e-this.bbox().y:0;return null==t?"number"==typeof e?e-i:e:this.attr("y","number"==typeof t?t+i:t)},cx:function(t){return null==t?this.bbox().cx:this.x(t-this.bbox().width/2)},cy:function(t){return null==t?this.bbox().cy:this.y(t-this.bbox().height/2)},text:function(t){if(void 0===t){var e=this.node.childNodes,i=0;t="";for(var n=0,r=e.length;n<r;++n)"textPath"!==e[n].nodeName?(n!==i&&3!==e[n].nodeType&&!0===w.adopt(e[n]).dom.newLined&&(t+="\n"),t+=e[n].textContent):0===n&&(i=1);return t}if(this.clear().build(!0),"function"==typeof t)t.call(this,this);else{t=t.split("\n");for(var s=0,o=t.length;s<o;s++)this.tspan(t[s]).newLine()}return this.build(!1).rebuild()},leading:function(t){return null==t?this.dom.leading:(this.dom.leading=new w.Number(t),this.rebuild())},rebuild:function(t){if("boolean"==typeof t&&(this._rebuild=t),this._rebuild){var e=this,i=0,n=this.dom.leading*new w.Number(this.attr("font-size"));this.each(function(){this.dom.newLined&&(this.attr("x",e.attr("x")),"\n"===this.text()?i+=n:(this.attr("dy",n+i),i=0))}),this.fire("rebuild")}return this},build:function(t){return this._build=!!t,this},setData:function(t){return this.dom=t,this.dom.leading=new w.Number(t.leading||1.3),this}},construct:{text:function(t){return this.put(new w.Text).text(t)},plain:function(t){return this.put(new w.Text).plain(t)}}}),w.Tspan=w.invent({create:"tspan",inherit:w.Parent,extend:{text:function(t){return null==t?this.node.textContent+(this.dom.newLined?"\n":""):("function"==typeof t?t.call(this,this):this.plain(t),this)},dx:function(t){return this.attr("dx",t)},dy:function(t){return this.attr("dy",t)},newLine:function(){var t=this.parent(w.Text);return this.dom.newLined=!0,this.dy(t.dom.leading*t.attr("font-size")).attr("x",t.x())}}}),w.extend([w.Text,w.Tspan],{plain:function(t){return!1===this._build&&this.clear(),this.node.appendChild(e.createTextNode(t)),this},tspan:function(t){var e=new w.Tspan;return this._build||this.clear(),this.node.appendChild(e.node),e.text(t)},length:function(){return this.node.getComputedTextLength()}}),w.TextPath=w.invent({create:"textPath",inherit:w.Text,parent:w.Parent,extend:{MorphArray:w.PathArray,array:function(){var t=this.track();return t?t.array():null},plot:function(t){var e=this.track(),i=null;return e&&(i=e.plot(t)),null==t?i:this},track:function(){return this.reference("href")}},construct:{textPath:function(t,e){return this.defs().path(e).text(t).addTo(this)}}}),w.extend([w.Text],{path:function(t){var e=new w.TextPath;return t instanceof w.Path||(t=this.doc().defs().path(t)),e.attr("href","#"+t,w.xlink),this.put(e)},textPath:function(){return this.select("textPath")}}),w.extend([w.Path],{text:function(t){if(t instanceof w.Text){var e=t.text();return t.clear().path(this).text(e)}return this.parent().put(new w.Text).path(this).text(t)}}),w.A=w.invent({create:"a",inherit:w.Container,extend:{to:function(t){return this.attr("href",t,w.xlink)},target:function(t){return this.attr("target",t)}},construct:{link:function(t){return this.put(new w.A).to(t)}}}),w.extend(w.Element,{linkTo:function(t){var e=new w.A;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}),w.Marker=w.invent({create:"marker",inherit:w.Container,extend:{width:function(t){return this.attr("markerWidth",t)},height:function(t){return this.attr("markerHeight",t)},ref:function(t,e){return this.attr("refX",t).attr("refY",e)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return"url(#"+this.id()+")"}},construct:{marker:function(t,e,i){return this.defs().marker(t,e,i)}}}),w.extend(w.Defs,{marker:function(t,e,i){return this.put(new w.Marker).size(t,e).ref(t/2,e/2).viewbox(0,0,t,e).attr("orient","auto").update(i)}}),w.extend([w.Line,w.Polyline,w.Polygon,w.Path],{marker:function(t,e,i,n){var r=["marker"];return"all"!==t&&r.push(t),r=r.join("-"),t=arguments[1]instanceof w.Marker?arguments[1]:this.doc().marker(e,i,n),this.attr(r,t)}}),w.extend(w.Element,{data:function(t,e,i){if("object"==typeof t)for(e in t)this.data(e,t[e]);else if(arguments.length<2)try{return JSON.parse(this.attr("data-"+t))}catch(e){return this.attr("data-"+t)}else this.attr("data-"+t,null===e?null:!0===i||"string"==typeof e||"number"==typeof e?e:JSON.stringify(e));return this}}),w.extend(w.Element,{remember:function(t,e){if("object"==typeof arguments[0])for(var i in t)this.remember(i,t[i]);else{if(1===arguments.length)return this.memory()[t];this.memory()[t]=e}return this},forget:function(){if(0===arguments.length)this._memory={};else for(var t=arguments.length-1;t>=0;t--)delete this.memory()[arguments[t]];return this},memory:function(){return this._memory||(this._memory={})}}),w.get=function(t){var i=e.getElementById(y(t)||t);return w.adopt(i)},w.select=function(t,i){return w.utils.map((i||e).querySelectorAll(t),function(t){return w.adopt(t)})},w.$$=function(t,i){return w.utils.map((i||e).querySelectorAll(t),function(t){return w.adopt(t)})},w.$=function(t,i){return w.adopt((i||e).querySelector(t))},w.extend(w.Parent,{select:function(t){return w.select(t,this.node)}});var N="abcdef".split("");return w.Box=w.invent({create:function(t){var e=[0,0,0,0];t="string"==typeof t?t.split(w.regex.delimiter).map(parseFloat):Array.isArray(t)?t:"object"==typeof t?[null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height]:4===arguments.length?[].slice.call(arguments):e,this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3],x(this)},extend:{merge:function(t){var e=Math.min(this.x,t.x),i=Math.min(this.y,t.y);return new w.Box(e,i,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-i)},transform:function(t){var e=1/0,i=-1/0,n=1/0,r=-1/0;return[new w.Point(this.x,this.y),new w.Point(this.x2,this.y),new w.Point(this.x,this.y2),new w.Point(this.x2,this.y2)].forEach(function(s){s=s.transform(t),e=Math.min(e,s.x),i=Math.max(i,s.x),n=Math.min(n,s.y),r=Math.max(r,s.y)}),new w.Box(e,n,i-e,r-n)},addOffset:function(){return this.x+=t.pageXOffset,this.y+=t.pageYOffset,this},toString:function(){return this.x+" "+this.y+" "+this.width+" "+this.height},morph:function(t,e,i,n){return this.destination=new w.Box(t,e,i,n),this},at:function(t){return this.destination?new w.Box(this.x+(this.destination.x-this.x)*t,this.y+(this.destination.y-this.y)*t,this.width+(this.destination.width-this.width)*t,this.height+(this.destination.height-this.height)*t):this}},parent:w.Element,construct:{bbox:function(){var t;try{if(t=this.node.getBBox(),n(t)&&!r(this.node))throw new Exception("Element not in the dom")}catch(i){try{var e=this.clone(w.parser().svg).show();t=e.node.getBBox(),e.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return new w.Box(t)},rbox:function(t){try{var e=new w.Box(this.node.getBoundingClientRect());return t?e.transform(t.screenCTM().inverse()):e.addOffset()}catch(t){return new w.Box}}}}),w.extend([w.Doc,w.Symbol,w.Image,w.Pattern,w.Marker,w.ForeignObject,w.View],{viewbox:function(t,e,i,n){return null==t?new w.Box(this.attr("viewBox")):this.attr("viewBox",new w.Box(t,e,i,n))}}),w.parser=function(){var t;return w.parser.nodes.svg.node.parentNode||(t=e.body||e.documentElement,w.parser.nodes.svg.addTo(t)),w.parser.nodes},w.parser.nodes={svg:w().size(2,0).css({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"})},w.parser.nodes.path=w.parser.nodes.svg.path().node,w}); \ No newline at end of file
diff --git a/gulpfile.js b/gulpfile.js
index 1d7870f..5b511ef 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -31,6 +31,8 @@ var parts = [
'src/regex.js',
'src/utilities.js',
'src/default.js',
+ 'src/queue.js',
+ 'src/drawLoop.js',
'src/color.js',
'src/array.js',
'src/pointarray.js',
diff --git a/spec/spec/circle.js b/spec/spec/circle.js
index c0f0936..0f2c8f4 100644
--- a/spec/spec/circle.js
+++ b/spec/spec/circle.js
@@ -1,3 +1,4 @@
+
describe('Circle', function() {
var circle
@@ -173,5 +174,4 @@ describe('Circle', function() {
expect(window.matrixStringToArray(circle.node.getAttribute('transform'))).toEqual([1,0,0,1,12,12])
})
})
-
})
diff --git a/spec/spec/queue.js b/spec/spec/queue.js
new file mode 100644
index 0000000..738831c
--- /dev/null
+++ b/spec/spec/queue.js
@@ -0,0 +1,111 @@
+
+describe ('SVG.Queue()', function () {
+
+ describe('first ()', function () {
+
+ it('returns null if no item in the queue', function () {
+ var queue = new SVG.Queue()
+ expect(queue.first()).toEqual(null)
+ })
+
+ it ('returns the first value in the queue', function () {
+ var queue = new SVG.Queue()
+ queue.push(1)
+ expect(queue.first()).toBe(1)
+ queue.push(2)
+ expect(queue.first()).toBe(1)
+ })
+ })
+
+ describe('last ()', function () {
+
+ it ('returns null if no item in the queue', function () {
+ var queue = new SVG.Queue()
+ expect(queue.last()).toEqual(null)
+ })
+
+ it ('returns the last value added', function () {
+ var queue = new SVG.Queue()
+ queue.push(1)
+ expect(queue.last()).toBe(1)
+ queue.push(2)
+ expect(queue.last()).toBe(2)
+ })
+ })
+
+ describe('push ()', function () {
+
+ it ('adds an element to the end of the queue', function () {
+ var queue = new SVG.Queue()
+ queue.push(1)
+ queue.push(2)
+ queue.push(3)
+
+ expect(queue.first()).toBe(1)
+ expect(queue.last()).toBe(3)
+ })
+
+ it ('changes the length when you add things', function () {
+ var queue = new SVG.Queue()
+ queue.push(1)
+ expect(queue.length).toBe(1)
+ queue.push(2)
+ expect(queue.length).toBe(2)
+ })
+ })
+
+ describe('remove ()', function () {
+ it('removes an item from the queue which matches the matcher', function () {
+ var queue = new SVG.Queue()
+ queue.push(1)
+ queue.push(2)
+ queue.push(3)
+
+ queue.remove(function(item) {
+ return item.value == 3
+ })
+
+ expect(queue.length).toBe(2)
+ expect(queue.last()).toBe(2)
+ expect(queue.first()).toBe(1)
+ })
+
+ it('removes no item from the queue if nothing is matched', function () {
+ var queue = new SVG.Queue()
+ queue.push(1)
+ queue.push(2)
+ queue.push(3)
+
+ queue.remove(function(item) {
+ return item.value == 4
+ })
+
+ expect(queue.length).toBe(3)
+ expect(queue.last()).toBe(3)
+ expect(queue.first()).toBe(1)
+ })
+ })
+
+ describe('shift ()', function () {
+ it('returns nothing if queue is empty', function () {
+ var queue = new SVG.Queue()
+ var val = queue.shift()
+ expect(val).toBeFalsy()
+ })
+
+ it('returns the first item of the queue and removes it', function () {
+ var queue = new SVG.Queue()
+ queue.push(1)
+ queue.push(2)
+ queue.push(3)
+
+ var val = queue.shift()
+
+ expect(queue.length).toBe(2)
+ expect(queue.last()).toBe(3)
+ expect(queue.first()).toBe(2)
+
+ expect(val).toBe(1)
+ })
+ })
+})
diff --git a/src/drawLoop.js b/src/drawLoop.js
new file mode 100644
index 0000000..6b6e6c3
--- /dev/null
+++ b/src/drawLoop.js
@@ -0,0 +1,82 @@
+
+SVG.Animator = {
+ nextDraw: null,
+ frames: new SVG.Queue(),
+ timeouts: new SVG.Queue(),
+ frameCount: 0,
+ timeoutCount: 0,
+ timer: window.performance || window.Date,
+
+ frame: function (fn) {
+ SVG.Animator.frames.push({
+ id: SVG.Animator.frameCount,
+ run: fn
+ })
+
+ if (SVG.Animator.nextDraw === null) {
+ SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw)
+ }
+
+ return ++SVG.Animator.frameCount
+ },
+
+ timeout: function (fn, delay) {
+ delay = delay || 0
+
+ // Work out when the event should fire
+ var time = SVG.Animator.timer.now() + delay
+
+ // Add the timeout to the end of the queue
+ var thisId = SVG.Animator.timeoutCount++
+ SVG.Animator.timeouts.push({
+ id: thisId,
+ run: fn,
+ time: time
+ })
+
+ // Request another animation frame if we need one
+ if (SVG.Animator.nextDraw === null) {
+ SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw)
+ }
+
+ return thisId
+ },
+
+ cancelTimeout: function (id) {
+ // Find the index of the timeout to cancel and remove it
+ var index = SVG.Animator.timeouts.remove(function (t) { return t.id == id })
+ return index
+ },
+
+ _draw: function (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 tracking = true
+ var nextTimeout = null
+ var lastTimeout = SVG.Animator.timeouts.last()
+ while ((nextTimeout = SVG.Animator.timeouts.shift())) {
+ // Run the timeout if its time, or push it to the end
+ if (now > nextTimeout.time) {
+ nextTimeout.run()
+ } else {
+ SVG.Animator.timeouts.push(nextTimeout)
+ }
+
+ // If we hit the last item, we should stop shifting out more items
+ if (nextTimeout === lastTimeout) break
+ }
+
+ // Run all of the frames available up until this point
+ var lastFrame = SVG.Animator.frames.last()
+ var lastFrameId = SVG.Animator.frameCount
+ while (SVG.Animator.frames.first() && SVG.Animator.frames.first().id < lastFrameId) {
+ var nextFrame = SVG.Animator.frames.shift()
+ nextFrame.run(now)
+ }
+
+ // If we have remaining timeouts or frames, draw until we don't anymore
+ SVG.Animator.nextDraw = SVG.Animator.timeouts.length > 0 || SVG.Animator.frames.length > 0
+ ? requestAnimationFrame(SVG.Animator._draw)
+ : null
+ }
+}
diff --git a/src/ellipse.js b/src/ellipse.js
index eb310f9..8a8f027 100644
--- a/src/ellipse.js
+++ b/src/ellipse.js
@@ -16,7 +16,7 @@ SVG.Circle = SVG.invent({
}
})
-SVG.extend([SVG.Circle, SVG.FX], {
+SVG.extend([SVG.Circle, SVG.Timeline], {
// Radius x value
rx: function (rx) {
return this.attr('r', rx)
@@ -43,7 +43,7 @@ SVG.Ellipse = SVG.invent({
}
})
-SVG.extend([SVG.Ellipse, SVG.Rect, SVG.FX], {
+SVG.extend([SVG.Ellipse, SVG.Rect, SVG.Timeline], {
// Radius x value
rx: function (rx) {
return this.attr('rx', rx)
diff --git a/src/fx.js b/src/fx.js
index 9fcdd4c..c94f747 100644
--- a/src/fx.js
+++ b/src/fx.js
@@ -11,895 +11,1341 @@ SVG.morph = function (pos) {
}
}
-SVG.Situation = SVG.invent({
+let time = window.performance || window.Date
- create: function (o) {
- this.init = false
- this.reversed = false
- this.reversing = false
+SVG.Timeline = SVG.invent ({
- this.duration = new SVG.Number(o.duration).valueOf()
- this.delay = new SVG.Number(o.delay).valueOf()
+ create: function () {
- this.start = +new Date() + this.delay
- this.finish = this.start + this.duration
- this.ease = o.ease
+ // Store all of the closures to animate
+ this._closures = []
- // this.loop is incremented from 0 to this.loops
- // it is also incremented when in an infinite loop (when this.loops is true)
- this.loop = 0
- this.loops = false
+ this._startTime = time.now()
+ this._duration = 0
+
+ this._running = true
+
+ },
+
+ extend: {
+
+ animate (duration, ease, delay, epoch) {
- this.animations = {
- // functionToCall: [list of morphable objects]
- // e.g. move: [SVG.Number, SVG.Number]
}
- this.attrs = {
- // holds all attributes which are not represented from a function svg.js provides
- // e.g. someAttr: SVG.Number
+ loop (times, reverse) {
+
}
- this.styles = {
- // holds all styles which should be animated
- // e.g. fill-color: SVG.Color
+ duration (time) {
+ this._duration = time
}
- this.transforms = [
- // holds all transformations as transformation objects
- // e.g. [SVG.Rotate, SVG.Translate, SVG.Matrix]
- ]
+ delay (by, epoch) {
+ if (epoch) {
+ this._startTime = time.now()
+ }
+ this._duration = 0
+ this._startTime += by
+ }
+
+ ease (fn) {
- this.once = {
- // functions to fire at a specific position
- // e.g. "0.5": function foo(){}
}
- }
-})
+ play ()
+ pause ()
+ stop ()
+ finish (all=true)
+ speed (newSpeed)
+ seek (dt)
+ persist (dt || forever) // 0 by default
+ reverse ()
-SVG.FX = SVG.invent({
-
- create: function (element) {
- this._target = element
- this.situations = []
- this.active = false
- this.situation = null
- this.paused = false
- this.lastPos = 0
- this.pos = 0
- // The absolute position of an animation is its position in the context of its complete duration (including delay and loops)
- // When performing a delay, absPos is below 0 and when performing a loop, its value is above 1
- this.absPos = 0
- this._speed = 1
- },
- extend: {
- /**
- * sets or returns the target of this animation
- * @param o object || number In case of Object it holds all parameters. In case of number its the duration of the animation
- * @param ease function || string Function which should be used for easing or easing keyword
- * @param delay Number indicating the delay before the animation starts
- * @return target || this
- */
- animate: function (o, ease, delay) {
- if (typeof o === 'object') {
- ease = o.ease
- delay = o.delay
- o = o.duration
- }
- var situation = new SVG.Situation({
- duration: o || 1000,
- delay: delay || 0,
- ease: SVG.easing[ease || '-'] || ease
- })
- this.queue(situation)
- return this
- },
+ // fn is a function that takes a position in range [0, 1]
+ schedule (fn) { // fn can not take parameters
- /**
- * sets a delay before the next element of the queue is called
- * @param delay Duration of delay in milliseconds
- * @return this.target()
- */
- delay: function (delay) {
- // The delay is performed by an empty situation with its duration
- // attribute set to the duration of the delay
- var situation = new SVG.Situation({
- duration: delay,
- delay: 0,
- ease: SVG.easing['-']
- })
- return this.queue(situation)
- },
- /**
- * sets or returns the target of this animation
- * @param null || target SVG.Element which should be set as new target
- * @return target || this
- */
- target: function (target) {
- if (target && target instanceof SVG.Element) {
- this._target = target
- return this
- }
- return this._target
- },
- // returns the absolute position at a given time
- timeToAbsPos: function (timestamp) {
- return (timestamp - this.situation.start) / (this.situation.duration / this._speed)
- },
- // returns the timestamp from a given absolute positon
- absPosToTime: function (absPos) {
- return this.situation.duration / this._speed * absPos + this.situation.start
- },
+let declarative = rect.animate(300, '>', 200)
+ .loop().color('blue')
+ .animate(SVG.Spring(300))
- // starts the animationloop
- startAnimFrame: function () {
- this.stopAnimFrame()
- this.animationFrame = window.requestAnimationFrame(function () { this.step() }.bind(this))
- },
+onmousemove() {
+ declarative.x(mouseX).y(mouseY)
+}
- // cancels the animationframe
- stopAnimFrame: function () {
- window.cancelAnimationFrame(this.animationFrame)
- },
+ SVG.MorphObj = SVG.invent({
- // kicks off the animation - only does something when the queue is currently not active and at least one situation is set
- start: function () {
- // dont start if already started
- if (!this.active && this.situation) {
- this.active = true
- this.startCurrent()
- }
+ create: function (from, to) {
+ // prepare color for morphing
+ if (SVG.Color.isColor(to)) return new SVG.Color(from).morph(to)
+ // prepare value list for morphing
+ if (SVG.regex.delimiter.test(from)) return new SVG.Array(from).morph(to)
+ // prepare number for morphing
+ if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to)
- return this
- },
+ // prepare for plain morphing
+ this.value = from
+ this.destination = to
+ },
- // start the current situation
- startCurrent: function () {
- this.situation.start = +new Date() + this.situation.delay / this._speed
- this.situation.finish = this.situation.start + this.situation.duration / this._speed
- return this.initAnimations().step()
- },
+ extend: {
+ at: function (pos, real) {
+ return real < 1 ? this.value : this.destination
+ },
- /**
- * adds a function / Situation to the animation queue
- * @param fn function / situation to add
- * @return this
- */
- queue: function (fn) {
- if (typeof fn === 'function' || fn instanceof SVG.Situation) {
- this.situations.push(fn)
- }
+ valueOf: function () {
+ return this.value
+ }
+ }
- if (!this.situation) this.situation = this.situations.shift()
+ })
- return this
- },
- /**
- * pulls next element from the queue and execute it
- * @return this
- */
- dequeue: function () {
- // stop current animation
- this.stop()
-
- // get next animation from queue
- this.situation = this.situations.shift()
-
- if (this.situation) {
- if (this.situation instanceof SVG.Situation) {
- this.start()
- } else {
- // If it is not a SVG.Situation, then it is a function, we execute it
- this.situation(this)
- }
- }
+add('fill-color', val)
- return this
- },
+add('x', val, 'animations')
- // updates all animations to the current state of the element
- // this is important when one property could be changed from another property
- initAnimations: function () {
- var i, j, source
- var s = this.situation
+add('x', val, 'styles')
- if (s.init) return this
+add('line-cap', val, 'attrs')
- for (i in s.animations) {
- source = this.target()[i]()
+.style(name, val) {
- if (!Array.isArray(source)) {
- source = [source]
- }
- if (!Array.isArray(s.animations[i])) {
- s.animations[i] = [s.animations[i]]
- }
+ styleAttr ('style', name, val)
+}
- // if(s.animations[i].length > source.length) {
- // source.concat = source.concat(s.animations[i].slice(source.length, s.animations[i].length))
- // }
+.animate(spring)
- for (j = source.length; j--;) {
- // The condition is because some methods return a normal number instead
- // of a SVG.Number
- if (s.animations[i][j] instanceof SVG.Number) {
- source[j] = new SVG.Number(source[j])
- }
+onmousemove(() => {
+ el.animate(SVG.Spring(500))
+ .move(event.pointX, event.pointY)
+ .finish()
+})
- s.animations[i][j] = source[j].morph(s.animations[i][j])
- }
- }
- for (i in s.attrs) {
- s.attrs[i] = new SVG.MorphObj(this.target().attr(i), s.attrs[i])
- }
- for (i in s.styles) {
- s.styles[i] = new SVG.MorphObj(this.target().css(i), s.styles[i])
- }
+Morphable ()
- s.initialTransformation = this.target().matrixify()
+Controlable ()
- s.init = true
- return this
- },
+new Controller(target, controller)
- clearQueue: function () {
- this.situations = []
- return this
- },
- clearCurrent: function () {
- this.situation = null
- return this
+SVG.Timeline = {
+ styleAttr (type, name, val) {
+ let morpher = new Morph(this.controller).to(val)
+ queue (
+ ()=> {
+ morpher = morpher.from(element[type]('name'))
+ },
+ morpher.at
+ )
+ }
+}
+
+.styleAttr (type, name, val) {
+
+ let morpher = declarative ? new Controller(target) : new Morph().to(val)
+ queue (
+ ()=> {
+ morpher = morpher.from(element[type]('name'))
},
+ () => {
+ this.element[type](name, morpher.at(pos))
+ }
+ )
+}
- /** stops the animation immediately
- * @param jumpToEnd A Boolean indicating whether to complete the current animation immediately.
- * @param clearQueue A Boolean indicating whether to remove queued animation as well.
- * @return this
- */
- stop: function (jumpToEnd, clearQueue) {
- var active = this.active
- this.active = false
-
- if (clearQueue) {
- this.clearQueue()
- }
+viewbox(box) {
+ new Box
+ let morpher = new Morph().to(box) // box: {width, heught, x, y}
+}
- if (jumpToEnd && this.situation) {
- // initialize the situation if it was not
- !active && this.startCurrent()
- this.atEnd()
- }
- this.stopAnimFrame()
+new Morph(from, to)
- return this.clearCurrent()
- },
- /** resets the element to the state where the current element has started
- * @return this
- */
- reset: function () {
- if (this.situation) {
- var temp = this.situation
- this.stop()
- this.situation = temp
- this.atStart()
- }
- return this
- },
+new Morpg(from, to, controller = (from, to, pos) => {from + pos * (to - from)})
- // Stop the currently-running animation, remove all queued animations, and complete all animations for the element.
- finish: function () {
- this.stop(true, false)
- while (this.dequeue().situation && this.stop(true, false));
+// Something line
+path = "a, b, c"
- this.clearQueue().clearCurrent()
+SVG.color {
+ toArray: [r, g, b]
+ fromArray: new Color({r, g, b})
+}
- return this
- },
- // set the internal animation pointer at the start position, before any loops, and updates the visualisation
- atStart: function () {
- return this.at(0, true)
- },
- // set the internal animation pointer at the end position, after all the loops, and updates the visualisation
- atEnd: function () {
- if (this.situation.loops === true) {
- // If in a infinite loop, we end the current iteration
- this.situation.loops = this.situation.loop + 1
- }
- if (typeof this.situation.loops === 'number') {
- // If performing a finite number of loops, we go after all the loops
- return this.at(this.situation.loops, true)
- } else {
- // If no loops, we just go at the end
- return this.at(1, true)
- }
- },
- // set the internal animation pointer to the specified position and updates the visualisation
- // if isAbsPos is true, pos is treated as an absolute position
- at: function (pos, isAbsPos) {
- var durDivSpd = this.situation.duration / this._speed
- this.absPos = pos
- // If pos is not an absolute position, we convert it into one
- if (!isAbsPos) {
- if (this.situation.reversed) this.absPos = 1 - this.absPos
- this.absPos += this.situation.loop
- }
+morph: function (pathArray) {
+ pathArray = new SVG.PathArray(pathArray)
- this.situation.start = +new Date() - this.absPos * durDivSpd
- this.situation.finish = this.situation.start + durDivSpd
+ if (this.equalCommands(pathArray)) {
+ this.destination = pathArray
+ } else {
+ this.destination = null
+ }
- return this.step(true)
- },
+ return this
+},
- /**
- * sets or returns the speed of the animations
- * @param speed null || Number The new speed of the animations
- * @return Number || this
- */
- speed: function (speed) {
- if (speed === 0) return this.pause()
-
- if (speed) {
- this._speed = speed
- // We use an absolute position here so that speed can affect the delay before the animation
- return this.at(this.absPos, true)
- } else return this._speed
- },
+[['M', 3, 5], ['L', 5, 6]]
- // Make loopable
- loop: function (times, reverse) {
- var c = this.last()
+['M', 3, 4, 'L', ...]
- // store total loops
- c.loops = (times != null) ? times : true
- c.loop = 0
- if (reverse) c.reversing = true
- return this
- },
- // pauses the animation
- pause: function () {
- this.paused = true
- this.stopAnimFrame()
- return this
- },
+function detectSomething (item) {
+ if(from instanceof SVG.Morphable) return from.controller(controller)
+ // prepare color for morphing
+ if (SVG.Color.isColor(to)) return new SVG.Color(from, controller)
+ // prepare value list for morphing
+ if (SVG.regex.delimiter.test(from)) return new SVG.Array(from).morph(to)
+ // prepare number for morphing
+ if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to)
- // unpause the animation
- play: function () {
- if (!this.paused) return this
- this.paused = false
- // We use an absolute position here so that the delay before the animation can be paused
- return this.at(this.absPos, true)
- },
+ return item
+}
- /**
- * toggle or set the direction of the animation
- * true sets direction to backwards while false sets it to forwards
- * @param reversed Boolean indicating whether to reverse the animation or not (default: toggle the reverse status)
- * @return this
- */
- reverse: function (reversed) {
- var c = this.last()
+foo->bar
- if (typeof reversed === 'undefined') c.reversed = !c.reversed
- else c.reversed = reversed
- return this
- },
+all of these things implement
- /**
- * returns a float from 0-1 indicating the progress of the current animation
- * @param eased Boolean indicating whether the returned position should be eased or not
- * @return number
- */
- progress: function (easeIt) {
- return easeIt ? this.situation.ease(this.pos) : this.pos
- },
+interface Morphable {
+ from: (thing)=> {}
+ to: (thing)=> {}
+ at: (pos)=> {}
+ controller: (fn (nowOrFrom, target, pos))=> {}
+}
- /**
- * adds a callback function which is called when the current animation is finished
- * @param fn Function which should be executed as callback
- * @return number
- */
- after: function (fn) {
- var c = this.last()
- function wrapper (e) {
- if (e.detail.situation === c) {
- fn.call(this, c)
- this.off('finished.fx', wrapper) // prevent memory leak
- }
- }
- this.target().on('finished.fx', wrapper)
+new SVG.MorphObj(el.attr(name))
- return this._callStart()
- },
+animate().attr('line-joint', 5)
- // adds a callback which is called whenever one animation step is performed
- during: function (fn) {
- var c = this.last()
- function wrapper (e) {
- if (e.detail.situation === c) {
- fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, c)
- }
- }
+SVG.MorphObj = SVG.invent({
- // see above
- this.target().off('during.fx', wrapper).on('during.fx', wrapper)
+ create: function (from, to) {
+ // prepare color for morphing
+ if (SVG.Color.isColor(to)) return new SVG.Color(from).morph(to)
+ // prepare value list for morphing
+ if (SVG.regex.delimiter.test(from)) return new SVG.Array(from).morph(to)
+ // prepare number for morphing
+ if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to)
- this.after(function () {
- this.off('during.fx', wrapper)
- })
+ // prepare for plain morphing
+ this.value = from
+ this.destination = to
+ },
- return this._callStart()
+ extend: {
+ at: function (pos, real) {
+ return real < 1 ? this.value : this.destination
},
- // calls after ALL animations in the queue are finished
- afterAll: function (fn) {
- var wrapper = function wrapper (e) {
- fn.call(this)
- this.off('allfinished.fx', wrapper)
- }
+ valueOf: function () {
+ return this.value
+ }
+ }
- // see above
- this.target().off('allfinished.fx', wrapper).on('allfinished.fx', wrapper)
+})
- return this._callStart()
- },
- // calls on every animation step for all animations
- duringAll: function (fn) {
- var wrapper = function (e) {
- fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, e.detail.situation)
- }
+// Only works with a single number
+new MorphObj {
- this.target().off('during.fx', wrapper).on('during.fx', wrapper)
+ constr: (control= (from, to, c)=> {from + pos * (to - from)}) {
+ }
- this.afterAll(function () {
- this.off('during.fx', wrapper)
- })
+ _detect: // Gets the user input and returns the right kind of object
- return this._callStart()
- },
+ from: (from) => {
- last: function () {
- return this.situations.length ? this.situations[this.situations.length - 1] : this.situation
- },
+ if (SVG.Color.isColor(to)) return new SVG.Color(from).morph(to)
+ // prepare value list for morphing
+ if (SVG.regex.delimiter.test(from)) return new SVG.Array(from).morph(to)
+ // prepare number for morphing
+ if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to)
- // adds one property to the animations
- add: function (method, args, type) {
- this.last()[type || 'animations'][method] = args
- return this._callStart()
- },
+ // prepare for plain morphing
+ this.value = from
+ this.destination = to
+ }
- /** perform one step of the animation
- * @param ignoreTime Boolean indicating whether to ignore time and use position directly or recalculate position based on time
- * @return this
- */
- step: function (ignoreTime) {
- // convert current time to an absolute position
- if (!ignoreTime) this.absPos = this.timeToAbsPos(+new Date())
-
- // This part convert an absolute position to a position
- if (this.situation.loops !== false) {
- var absPos, absPosInt, lastLoop
-
- // If the absolute position is below 0, we just treat it as if it was 0
- absPos = Math.max(this.absPos, 0)
- absPosInt = Math.floor(absPos)
-
- if (this.situation.loops === true || absPosInt < this.situation.loops) {
- this.pos = absPos - absPosInt
- lastLoop = this.situation.loop
- this.situation.loop = absPosInt
- } else {
- this.absPos = this.situation.loops
- this.pos = 1
- // The -1 here is because we don't want to toggle reversed when all the loops have been completed
- lastLoop = this.situation.loop - 1
- this.situation.loop = this.situation.loops
- }
+ to: (val) => {
- if (this.situation.reversing) {
- // Toggle reversed if an odd number of loops as occured since the last call of step
- this.situation.reversed = this.situation.reversed !== Boolean((this.situation.loop - lastLoop) % 2)
- }
- } else {
- // If there are no loop, the absolute position must not be above 1
- this.absPos = Math.min(this.absPos, 1)
- this.pos = this.absPos
- }
+ }
+ at (pos) {
- // while the absolute position can be below 0, the position must not be below 0
- if (this.pos < 0) this.pos = 0
+ let type = from.type
+ let from = from.toArray()
+ let to = to.toArray()
+ result = []
+ for (i)
+ result[i] = this.controller(from[i], to[i], pos) : to[i]
- if (this.situation.reversed) this.pos = 1 - this.pos
+ type.fromArray(result)
+ }
+}
- // apply easing
- var eased = this.situation.ease(this.pos)
+if(declartive) {
+ mropher.init()
+ morpher.at(pos/fn)
+}
- // call once-callbacks
- for (var i in this.situation.once) {
- if (i > this.lastPos && i <= eased) {
- this.situation.once[i].call(this.target(), this.pos, eased)
- delete this.situation.once[i]
- }
- }
- // fire during callback with position, eased position and current situation as parameter
- if (this.active) this.target().fire('during', {pos: this.pos, eased: eased, fx: this, situation: this.situation})
- // the user may call stop or finish in the during callback
- // so make sure that we still have a valid situation
- if (!this.situation) {
- return this
- }
+controller(currentPos, target)
- // apply the actual animation to every property
- this.eachAt()
- // do final code when situation is finished
- if ((this.pos === 1 && !this.situation.reversed) || (this.situation.reversed && this.pos === 0)) {
- // stop animation callback
- this.stopAnimFrame()
+morph interface
+detect type function
- // fire finished callback with current situation as parameter
- this.target().fire('finished', {fx: this, situation: this.situation})
- if (!this.situations.length) {
- this.target().fire('allfinished')
+if (mouse in box)
+ move box
+ animate(spring)
- // Recheck the length since the user may call animate in the afterAll callback
- if (!this.situations.length) {
- this.target().off('.fx') // there shouldnt be any binding left, but to make sure...
- this.active = false
- }
- }
+zoom(level, point) {
+ let morpher = SVG.Number(level).controller(this.controller)
+ this.queue(
+ () => {morpher = morpher.from(element.zoom())},
+ (pos) => {element.zoom(morpher.at(pos), point)}
+ )
+}
- // start next animation
- if (this.active) this.dequeue()
- else this.clearCurrent()
- } else if (!this.paused && this.active) {
- // we continue animating when we are not at the end
- this.startAnimFrame()
- }
+x (x) {
- // save last eased position for once callback triggering
- this.lastPos = eased
- return this
- },
+}
- // calculates the step for every property and calls block with it
- eachAt: function () {
- var i, at
- var self = this
- var target = this.target()
- var s = this.situation
+this.queue(fn, morpher)
- // apply animations which can be called trough a method
- for (i in s.animations) {
- at = [].concat(s.animations[i]).map(function (el) {
- return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el
- })
+new Morph(x(), xGiven)
- target[i].apply(target, at)
- }
- // apply animation which has to be applied with attr()
- for (i in s.attrs) {
- at = [i].concat(s.attrs[i]).map(function (el) {
- return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el
- })
+ x: function (x, relative) {
+ if (this.target() instanceof SVG.G) {
+ this.transform({x: x}, relative)
+ return this
+ }
- target.attr.apply(target, at)
- }
+ var num = new SVG.Number(x)
+ num.relative = relative
+ return this.add('x', num)
+ },
- // apply animation which has to be applied with css()
- for (i in s.styles) {
- at = [i].concat(s.styles[i]).map(function (el) {
- return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el
- })
- target.css.apply(target, at)
+ viewbox: function(box) {
+ var m = SVG.Box(box)
}
- // animate initialTransformation which has to be chained
- if (s.transforms.length) {
-
- // TODO: ANIMATE THE TRANSFORMS
-
- // // get initial initialTransformation
- // at = s.initialTransformation
- // for(i = 0, len = s.transforms.length; i < len; i++){
- //
- // // get next transformation in chain
- // var a = s.transforms[i]
- //
- // // multiply matrix directly
- // if(a instanceof SVG.Matrix){
- //
- // if(a.relative){
- // at = at.multiply(new SVG.Matrix().morph(a).at(s.ease(this.pos)))
- // }else{
- // at = at.morph(a).at(s.ease(this.pos))
- // }
- // continue
- // }
- //
- // // when transformation is absolute we have to reset the needed transformation first
- // if(!a.relative)
- // a.undo(at.decompose())
- //
- // // and reapply it after
- // at = at.multiply(a.at(s.ease(this.pos)))
- //
- // }
- //
- // // set new matrix on element
- // target.matrix(at)
- }
- return this
- },
+ new Runner (function(time) {
- // adds an once-callback which is called at a specific position and never again
- once: function (pos, fn, isEased) {
- var c = this.last()
- if (!isEased) pos = c.ease(pos)
- c.once[pos] = fn
+ })
- return this
- },
- _callStart: function () {
- setTimeout(function () { this.start() }.bind(this), 0)
- return this
- }
+ var closure = function (time) {
- },
+ // If it is time to do something, act now.
+ var running = start < time && time < end
+ if (running && this._running) {
+ closure.position = (time - closure.start) / closure.duration
+ fn (time)
+ }
- parent: SVG.Element,
+ // If we are not paused or stopped, request another frame
+ if (this._running) SVG.Animator.frame(closure, this._startTime)
- // Add method to parent elements
- construct: {
- // Get fx module or create a new one, then animate with given duration and ease
- animate: function (o, ease, delay) {
- return (this.fx || (this.fx = new SVG.FX(this))).animate(o, ease, delay)
- },
- delay: function (delay) {
- return (this.fx || (this.fx = new SVG.FX(this))).delay(delay)
- },
- stop: function (jumpToEnd, clearQueue) {
- if (this.fx) {
- this.fx.stop(jumpToEnd, clearQueue)
- }
+ // Tell the caller whether this animation is finished
+ closure.finished = !running
- return this
- },
- finish: function () {
- if (this.fx) {
- this.fx.finish()
- }
+ }.bind(this)
- return this
- },
- // Pause current animation
- pause: function () {
- if (this.fx) {
- this.fx.pause()
- }
+ closure.stop() // toggles a stop flag
+ closure.pause()
+ closure.run(t) // If it was paused, it
- return this
- },
- // Play paused current animation
- play: function () {
- if (this.fx) { this.fx.play() }
- return this
- },
- // Set/Get the speed of the animations
- speed: function (speed) {
- if (this.fx) {
- if (speed == null) { return this.fx.speed() } else { this.fx.speed(speed) }
- }
+ closure.start = this._startTime
+ closure.end = this._startTime + this._duration
+ closure.positon =
+ var forwards = true // Decide if running forward based on looping
- return this
+
+ // TODO: Store a list of closures
+
+ SVG.Animator.timeout(closure, this._startTime)
+ _continue()
}
- }
-})
+ _step (dt) {
-// MorphObj is used whenever no morphable object is given
-SVG.MorphObj = SVG.invent({
+ }
- create: function (from, to) {
- // prepare color for morphing
- if (SVG.Color.isColor(to)) return new SVG.Color(from).morph(to)
- // prepare value list for morphing
- if (SVG.regex.delimiter.test(from)) return new SVG.Array(from).morph(to)
- // prepare number for morphing
- if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to)
+ // Checks if we are running and continues the animation
+ _continue () {
+ , continue: function () {
+ if (this.paused) return
+ if (!this.nextFrame)
+ this.step()
+ return this
+ }
- // prepare for plain morphing
- this.value = from
- this.destination = to
+ }
},
- extend: {
- at: function (pos, real) {
- return real < 1 ? this.value : this.destination
- },
- valueOf: function () {
- return this.value
+ construct: {
+ animate: function(o, ease, delay, epoch) {
+ return (this.timeline = this.timeline || new SVG.Timeline(o, ease, delay, epoch))
}
}
-
})
-SVG.extend(SVG.FX, {
- // Add animatable attributes
- attr: function (a, v, relative) {
- // apply attributes individually
- if (typeof a === 'object') {
- for (var key in a) {
- this.attr(key, a[key])
- }
- } else {
- this.add(a, v, 'attrs')
- }
- return this
- },
- // Add animatable styles
- css: function (s, v) {
- if (typeof s === 'object') {
- for (var key in s) {
- this.css(key, s[key])
- }
- } else {
- this.add(s, v, 'styles')
- }
- return this
- },
- // Animatable x-axis
- x: function (x, relative) {
- if (this.target() instanceof SVG.G) {
- this.transform({x: x}, relative)
- return this
- }
- var num = new SVG.Number(x)
- num.relative = relative
- return this.add('x', num)
- },
- // Animatable y-axis
- y: function (y, relative) {
- if (this.target() instanceof SVG.G) {
- this.transform({y: y}, relative)
- return this
- }
- var num = new SVG.Number(y)
- num.relative = relative
- return this.add('y', num)
- },
- // Animatable center x-axis
- cx: function (x) {
- return this.add('cx', new SVG.Number(x))
- },
- // Animatable center y-axis
- cy: function (y) {
- return this.add('cy', new SVG.Number(y))
- },
- // Add animatable move
- move: function (x, y) {
- return this.x(x).y(y)
- },
- // Add animatable center
- center: function (x, y) {
- return this.cx(x).cy(y)
- },
- // Add animatable size
- size: function (width, height) {
- if (this.target() instanceof SVG.Text) {
- // animate font size for Text elements
- this.attr('font-size', width)
- } else {
- // animate bbox based size for all other elements
- var box
-
- if (!width || !height) {
- box = this.target().bbox()
- }
- if (!width) {
- width = box.width / box.height * height
- }
- if (!height) {
- height = box.height / box.width * width
- }
- this.add('width', new SVG.Number(width))
- .add('height', new SVG.Number(height))
- }
- return this
- },
- // Add animatable width
- width: function (width) {
- return this.add('width', new SVG.Number(width))
- },
- // Add animatable height
- height: function (height) {
- return this.add('height', new SVG.Number(height))
- },
- // Add animatable plot
- plot: function (a, b, c, d) {
- // Lines can be plotted with 4 arguments
- if (arguments.length === 4) {
- return this.plot([a, b, c, d])
- }
- return this.add('plot', new (this.target().MorphArray)(a))
- },
- // Add leading method
- leading: function (value) {
- return this.target().leading
- ? this.add('leading', new SVG.Number(value))
- : this
- },
- // Add animatable viewbox
- viewbox: function (x, y, width, height) {
- if (this.target() instanceof SVG.Container) {
- this.add('viewbox', new SVG.Box(x, y, width, height))
- }
- return this
- },
- update: function (o) {
- if (this.target() instanceof SVG.Stop) {
- if (typeof o === 'number' || o instanceof SVG.Number) {
- 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)
- }
- return this
- }
-})
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// SVG.Situation = SVG.invent({
+//
+// create: function (o) {
+// this.init = false
+// this.reversed = false
+// this.reversing = false
+//
+// this.duration = new SVG.Number(o.duration).valueOf()
+// this.delay = new SVG.Number(o.delay).valueOf()
+//
+// this.start = +new Date() + this.delay
+// this.finish = this.start + this.duration
+// this.ease = o.ease
+//
+// // this.loop is incremented from 0 to this.loops
+// // it is also incremented when in an infinite loop (when this.loops is true)
+// this.loop = 0
+// this.loops = false
+//
+// this.animations = {
+// // functionToCall: [list of morphable objects]
+// // e.g. move: [SVG.Number, SVG.Number]
+// }
+//
+// this.attrs = {
+// // holds all attributes which are not represented from a function svg.js provides
+// // e.g. someAttr: SVG.Number
+// }
+//
+// this.styles = {
+// // holds all styles which should be animated
+// // e.g. fill-color: SVG.Color
+// }
+//
+// this.transforms = [
+// // holds all transformations as transformation objects
+// // e.g. [SVG.Rotate, SVG.Translate, SVG.Matrix]
+// ]
+//
+// this.once = {
+// // functions to fire at a specific position
+// // e.g. "0.5": function foo(){}
+// }
+// }
+//
+// })
+//
+// SVG.Timeline = SVG.invent({
+//
+// create: function (element) {
+// this._target = element
+// this.situations = []
+// this.active = false
+// this.situation = null
+// this.paused = false
+// this.lastPos = 0
+// this.pos = 0
+// // The absolute position of an animation is its position in the context of its complete duration (including delay and loops)
+// // When performing a delay, absPos is below 0 and when performing a loop, its value is above 1
+// this.absPos = 0
+// this._speed = 1
+// },
+//
+// extend: {
+//
+// /**
+// * sets or returns the target of this animation
+// * @param o object || number In case of Object it holds all parameters. In case of number its the duration of the animation
+// * @param ease function || string Function which should be used for easing or easing keyword
+// * @param delay Number indicating the delay before the animation starts
+// * @return target || this
+// */
+// animate: function (o, ease, delay) {
+// if (typeof o === 'object') {
+// ease = o.ease
+// delay = o.delay
+// o = o.duration
+// }
+//
+// var situation = new SVG.Situation({
+// duration: o || 1000,
+// delay: delay || 0,
+// ease: SVG.easing[ease || '-'] || ease
+// })
+//
+// this.queue(situation)
+//
+// return this
+// },
+//
+// /**
+// * sets a delay before the next element of the queue is called
+// * @param delay Duration of delay in milliseconds
+// * @return this.target()
+// */
+// delay: function (delay) {
+// // The delay is performed by an empty situation with its duration
+// // attribute set to the duration of the delay
+// var situation = new SVG.Situation({
+// duration: delay,
+// delay: 0,
+// ease: SVG.easing['-']
+// })
+//
+// return this.queue(situation)
+// },
+//
+// /**
+// * sets or returns the target of this animation
+// * @param null || target SVG.Element which should be set as new target
+// * @return target || this
+// */
+// target: function (target) {
+// if (target && target instanceof SVG.Element) {
+// this._target = target
+// return this
+// }
+//
+// return this._target
+// },
+//
+// // returns the absolute position at a given time
+// timeToAbsPos: function (timestamp) {
+// return (timestamp - this.situation.start) / (this.situation.duration / this._speed)
+// },
+//
+// // returns the timestamp from a given absolute positon
+// absPosToTime: function (absPos) {
+// return this.situation.duration / this._speed * absPos + this.situation.start
+// },
+//
+// // starts the animationloop
+// startAnimFrame: function () {
+// this.stopAnimFrame()
+// this.animationFrame = window.requestAnimationFrame(function () { this.step() }.bind(this))
+// },
+//
+// // cancels the animationframe
+// stopAnimFrame: function () {
+// window.cancelAnimationFrame(this.animationFrame)
+// },
+//
+// // kicks off the animation - only does something when the queue is currently not active and at least one situation is set
+// start: function () {
+// // dont start if already started
+// if (!this.active && this.situation) {
+// this.active = true
+// this.startCurrent()
+// }
+//
+// return this
+// },
+//
+// // start the current situation
+// startCurrent: function () {
+// this.situation.start = +new Date() + this.situation.delay / this._speed
+// this.situation.finish = this.situation.start + this.situation.duration / this._speed
+// return this.initAnimations().step()
+// },
+//
+// /**
+// * adds a function / Situation to the animation queue
+// * @param fn function / situation to add
+// * @return this
+// */
+// queue: function (fn) {
+// if (typeof fn === 'function' || fn instanceof SVG.Situation) {
+// this.situations.push(fn)
+// }
+//
+// if (!this.situation) this.situation = this.situations.shift()
+//
+// return this
+// },
+//
+// /**
+// * pulls next element from the queue and execute it
+// * @return this
+// */
+// dequeue: function () {
+// // stop current animation
+// this.stop()
+//
+// // get next animation from queue
+// this.situation = this.situations.shift()
+//
+// if (this.situation) {
+// if (this.situation instanceof SVG.Situation) {
+// this.start()
+// } else {
+// // If it is not a SVG.Situation, then it is a function, we execute it
+// this.situation(this)
+// }
+// }
+//
+// return this
+// },
+//
+// // updates all animations to the current state of the element
+// // this is important when one property could be changed from another property
+// initAnimations: function () {
+// var i, j, source
+// var s = this.situation
+//
+// if (s.init) return this
+//
+// for (i in s.animations) {
+// source = this.target()[i]()
+//
+// if (!Array.isArray(source)) {
+// source = [source]
+// }
+//
+// if (!Array.isArray(s.animations[i])) {
+// s.animations[i] = [s.animations[i]]
+// }
+//
+// // if(s.animations[i].length > source.length) {
+// // source.concat = source.concat(s.animations[i].slice(source.length, s.animations[i].length))
+// // }
+//
+// for (j = source.length; j--;) {
+// // The condition is because some methods return a normal number instead
+// // of a SVG.Number
+// if (s.animations[i][j] instanceof SVG.Number) {
+// source[j] = new SVG.Number(source[j])
+// }
+//
+// s.animations[i][j] = source[j].morph(s.animations[i][j])
+// }
+// }
+//
+// for (i in s.attrs) {
+// s.attrs[i] = new SVG.MorphObj(this.target().attr(i), s.attrs[i])
+// }
+//
+// for (i in s.styles) {
+// s.styles[i] = new SVG.MorphObj(this.target().css(i), s.styles[i])
+// }
+//
+// s.initialTransformation = this.target().matrixify()
+//
+// s.init = true
+// return this
+// },
+//
+// clearQueue: function () {
+// this.situations = []
+// return this
+// },
+//
+// clearCurrent: function () {
+// this.situation = null
+// return this
+// },
+//
+// /** stops the animation immediately
+// * @param jumpToEnd A Boolean indicating whether to complete the current animation immediately.
+// * @param clearQueue A Boolean indicating whether to remove queued animation as well.
+// * @return this
+// */
+// stop: function (jumpToEnd, clearQueue) {
+// var active = this.active
+// this.active = false
+//
+// if (clearQueue) {
+// this.clearQueue()
+// }
+//
+// if (jumpToEnd && this.situation) {
+// // initialize the situation if it was not
+// !active && this.startCurrent()
+// this.atEnd()
+// }
+//
+// this.stopAnimFrame()
+//
+// return this.clearCurrent()
+// },
+//
+// /** resets the element to the state where the current element has started
+// * @return this
+// */
+// reset: function () {
+// if (this.situation) {
+// var temp = this.situation
+// this.stop()
+// this.situation = temp
+// this.atStart()
+// }
+// return this
+// },
+//
+// // Stop the currently-running animation, remove all queued animations, and complete all animations for the element.
+// finish: function () {
+// this.stop(true, false)
+//
+// while (this.dequeue().situation && this.stop(true, false));
+//
+// this.clearQueue().clearCurrent()
+//
+// return this
+// },
+//
+// // set the internal animation pointer at the start position, before any loops, and updates the visualisation
+// atStart: function () {
+// return this.at(0, true)
+// },
+//
+// // set the internal animation pointer at the end position, after all the loops, and updates the visualisation
+// atEnd: function () {
+// if (this.situation.loops === true) {
+// // If in a infinite loop, we end the current iteration
+// this.situation.loops = this.situation.loop + 1
+// }
+//
+// if (typeof this.situation.loops === 'number') {
+// // If performing a finite number of loops, we go after all the loops
+// return this.at(this.situation.loops, true)
+// } else {
+// // If no loops, we just go at the end
+// return this.at(1, true)
+// }
+// },
+//
+// // set the internal animation pointer to the specified position and updates the visualisation
+// // if isAbsPos is true, pos is treated as an absolute position
+// at: function (pos, isAbsPos) {
+// var durDivSpd = this.situation.duration / this._speed
+//
+// this.absPos = pos
+// // If pos is not an absolute position, we convert it into one
+// if (!isAbsPos) {
+// if (this.situation.reversed) this.absPos = 1 - this.absPos
+// this.absPos += this.situation.loop
+// }
+//
+// this.situation.start = +new Date() - this.absPos * durDivSpd
+// this.situation.finish = this.situation.start + durDivSpd
+//
+// return this.step(true)
+// },
+//
+// /**
+// * sets or returns the speed of the animations
+// * @param speed null || Number The new speed of the animations
+// * @return Number || this
+// */
+// speed: function (speed) {
+// if (speed === 0) return this.pause()
+//
+// if (speed) {
+// this._speed = speed
+// // We use an absolute position here so that speed can affect the delay before the animation
+// return this.at(this.absPos, true)
+// } else return this._speed
+// },
+//
+// // Make loopable
+// loop: function (times, reverse) {
+// var c = this.last()
+//
+// // store total loops
+// c.loops = (times != null) ? times : true
+// c.loop = 0
+//
+// if (reverse) c.reversing = true
+// return this
+// },
+//
+// // pauses the animation
+// pause: function () {
+// this.paused = true
+// this.stopAnimFrame()
+//
+// return this
+// },
+//
+// // unpause the animation
+// play: function () {
+// if (!this.paused) return this
+// this.paused = false
+// // We use an absolute position here so that the delay before the animation can be paused
+// return this.at(this.absPos, true)
+// },
+//
+// /**
+// * toggle or set the direction of the animation
+// * true sets direction to backwards while false sets it to forwards
+// * @param reversed Boolean indicating whether to reverse the animation or not (default: toggle the reverse status)
+// * @return this
+// */
+// reverse: function (reversed) {
+// var c = this.last()
+//
+// if (typeof reversed === 'undefined') c.reversed = !c.reversed
+// else c.reversed = reversed
+//
+// return this
+// },
+//
+// /**
+// * returns a float from 0-1 indicating the progress of the current animation
+// * @param eased Boolean indicating whether the returned position should be eased or not
+// * @return number
+// */
+// progress: function (easeIt) {
+// return easeIt ? this.situation.ease(this.pos) : this.pos
+// },
+//
+// /**
+// * adds a callback function which is called when the current animation is finished
+// * @param fn Function which should be executed as callback
+// * @return number
+// */
+// after: function (fn) {
+// var c = this.last()
+// function wrapper (e) {
+// if (e.detail.situation === c) {
+// fn.call(this, c)
+// this.off('finished.fx', wrapper) // prevent memory leak
+// }
+// }
+//
+// this.target().on('finished.fx', wrapper)
+//
+// return this._callStart()
+// },
+//
+// // adds a callback which is called whenever one animation step is performed
+// during: function (fn) {
+// var c = this.last()
+// function wrapper (e) {
+// if (e.detail.situation === c) {
+// fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, c)
+// }
+// }
+//
+// // see above
+// this.target().off('during.fx', wrapper).on('during.fx', wrapper)
+//
+// this.after(function () {
+// this.off('during.fx', wrapper)
+// })
+//
+// return this._callStart()
+// },
+//
+// // calls after ALL animations in the queue are finished
+// afterAll: function (fn) {
+// var wrapper = function wrapper (e) {
+// fn.call(this)
+// this.off('allfinished.fx', wrapper)
+// }
+//
+// // see above
+// this.target().off('allfinished.fx', wrapper).on('allfinished.fx', wrapper)
+//
+// return this._callStart()
+// },
+//
+// // calls on every animation step for all animations
+// duringAll: function (fn) {
+// var wrapper = function (e) {
+// fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, e.detail.situation)
+// }
+//
+// this.target().off('during.fx', wrapper).on('during.fx', wrapper)
+//
+// this.afterAll(function () {
+// this.off('during.fx', wrapper)
+// })
+//
+// return this._callStart()
+// },
+//
+// last: function () {
+// return this.situations.length ? this.situations[this.situations.length - 1] : this.situation
+// },
+//
+// // adds one property to the animations
+// add: function (method, args, type) {
+// this.last()[type || 'animations'][method] = args
+// return this._callStart()
+// },
+//
+// /** perform one step of the animation
+// * @param ignoreTime Boolean indicating whether to ignore time and use position directly or recalculate position based on time
+// * @return this
+// */
+// step: function (ignoreTime) {
+// // convert current time to an absolute position
+// if (!ignoreTime) this.absPos = this.timeToAbsPos(+new Date())
+//
+// // This part convert an absolute position to a position
+// if (this.situation.loops !== false) {
+// var absPos, absPosInt, lastLoop
+//
+// // If the absolute position is below 0, we just treat it as if it was 0
+// absPos = Math.max(this.absPos, 0)
+// absPosInt = Math.floor(absPos)
+//
+// if (this.situation.loops === true || absPosInt < this.situation.loops) {
+// this.pos = absPos - absPosInt
+// lastLoop = this.situation.loop
+// this.situation.loop = absPosInt
+// } else {
+// this.absPos = this.situation.loops
+// this.pos = 1
+// // The -1 here is because we don't want to toggle reversed when all the loops have been completed
+// lastLoop = this.situation.loop - 1
+// this.situation.loop = this.situation.loops
+// }
+//
+// if (this.situation.reversing) {
+// // Toggle reversed if an odd number of loops as occured since the last call of step
+// this.situation.reversed = this.situation.reversed !== Boolean((this.situation.loop - lastLoop) % 2)
+// }
+// } else {
+// // If there are no loop, the absolute position must not be above 1
+// this.absPos = Math.min(this.absPos, 1)
+// this.pos = this.absPos
+// }
+//
+// // while the absolute position can be below 0, the position must not be below 0
+// if (this.pos < 0) this.pos = 0
+//
+// if (this.situation.reversed) this.pos = 1 - this.pos
+//
+// // apply easing
+// var eased = this.situation.ease(this.pos)
+//
+// // call once-callbacks
+// for (var i in this.situation.once) {
+// if (i > this.lastPos && i <= eased) {
+// this.situation.once[i].call(this.target(), this.pos, eased)
+// delete this.situation.once[i]
+// }
+// }
+//
+// // fire during callback with position, eased position and current situation as parameter
+// if (this.active) this.target().fire('during', {pos: this.pos, eased: eased, fx: this, situation: this.situation})
+//
+// // the user may call stop or finish in the during callback
+// // so make sure that we still have a valid situation
+// if (!this.situation) {
+// return this
+// }
+//
+// // apply the actual animation to every property
+// this.eachAt()
+//
+// // do final code when situation is finished
+// if ((this.pos === 1 && !this.situation.reversed) || (this.situation.reversed && this.pos === 0)) {
+// // stop animation callback
+// this.stopAnimFrame()
+//
+// // fire finished callback with current situation as parameter
+// this.target().fire('finished', {fx: this, situation: this.situation})
+//
+// if (!this.situations.length) {
+// this.target().fire('allfinished')
+//
+// // Recheck the length since the user may call animate in the afterAll callback
+// if (!this.situations.length) {
+// this.target().off('.fx') // there shouldnt be any binding left, but to make sure...
+// this.active = false
+// }
+// }
+//
+// // start next animation
+// if (this.active) this.dequeue()
+// else this.clearCurrent()
+// } else if (!this.paused && this.active) {
+// // we continue animating when we are not at the end
+// this.startAnimFrame()
+// }
+//
+// // save last eased position for once callback triggering
+// this.lastPos = eased
+// return this
+// },
+//
+// // calculates the step for every property and calls block with it
+// eachAt: function () {
+// var i, at
+// var self = this
+// var target = this.target()
+// var s = this.situation
+//
+// // apply animations which can be called trough a method
+// for (i in s.animations) {
+// at = [].concat(s.animations[i]).map(function (el) {
+// return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el
+// })
+//
+// target[i].apply(target, at)
+// }
+//
+// // apply animation which has to be applied with attr()
+// for (i in s.attrs) {
+// at = [i].concat(s.attrs[i]).map(function (el) {
+// return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el
+// })
+//
+// target.attr.apply(target, at)
+// }
+//
+// // apply animation which has to be applied with css()
+// for (i in s.styles) {
+// at = [i].concat(s.styles[i]).map(function (el) {
+// return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el
+// })
+//
+// target.css.apply(target, at)
+// }
+//
+// // animate initialTransformation which has to be chained
+// if (s.transforms.length) {
+//
+// // TODO: ANIMATE THE TRANSFORMS
+//
+// // // get initial initialTransformation
+// // at = s.initialTransformation
+// // for(i = 0, len = s.transforms.length; i < len; i++){
+// //
+// // // get next transformation in chain
+// // var a = s.transforms[i]
+// //
+// // // multiply matrix directly
+// // if(a instanceof SVG.Matrix){
+// //
+// // if(a.relative){
+// // at = at.multiply(new SVG.Matrix().morph(a).at(s.ease(this.pos)))
+// // }else{
+// // at = at.morph(a).at(s.ease(this.pos))
+// // }
+// // continue
+// // }
+// //
+// // // when transformation is absolute we have to reset the needed transformation first
+// // if(!a.relative)
+// // a.undo(at.decompose())
+// //
+// // // and reapply it after
+// // at = at.multiply(a.at(s.ease(this.pos)))
+// //
+// // }
+// //
+// // // set new matrix on element
+// // target.matrix(at)
+// }
+//
+// return this
+// },
+//
+// // adds an once-callback which is called at a specific position and never again
+// once: function (pos, fn, isEased) {
+// var c = this.last()
+// if (!isEased) pos = c.ease(pos)
+//
+// c.once[pos] = fn
+//
+// return this
+// },
+//
+// _callStart: function () {
+// setTimeout(function () { this.start() }.bind(this), 0)
+// return this
+// }
+//
+// },
+//
+// parent: SVG.Element,
+//
+// // Add method to parent elements
+// construct: {
+// // Get fx module or create a new one, then animate with given duration and ease
+// animate: function (o, ease, delay) {
+// return (this.fx || (this.fx = new SVG.Timeline(this))).animate(o, ease, delay)
+// },
+// delay: function (delay) {
+// return (this.fx || (this.fx = new SVG.Timeline(this))).delay(delay)
+// },
+// stop: function (jumpToEnd, clearQueue) {
+// if (this.fx) {
+// this.fx.stop(jumpToEnd, clearQueue)
+// }
+//
+// return this
+// },
+// finish: function () {
+// if (this.fx) {
+// this.fx.finish()
+// }
+//
+// return this
+// },
+// // Pause current animation
+// pause: function () {
+// if (this.fx) {
+// this.fx.pause()
+// }
+//
+// return this
+// },
+// // Play paused current animation
+// play: function () {
+// if (this.fx) { this.fx.play() }
+//
+// return this
+// },
+// // Set/Get the speed of the animations
+// speed: function (speed) {
+// if (this.fx) {
+// if (speed == null) { return this.fx.speed() } else { this.fx.speed(speed) }
+// }
+//
+// return this
+// }
+// }
+//
+// })
+//
+// // MorphObj is used whenever no morphable object is given
+// SVG.MorphObj = SVG.invent({
+//
+// create: function (from, to) {
+// // prepare color for morphing
+// if (SVG.Color.isColor(to)) return new SVG.Color(from).morph(to)
+// // prepare value list for morphing
+// if (SVG.regex.delimiter.test(from)) return new SVG.Array(from).morph(to)
+// // prepare number for morphing
+// if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to)
+//
+// // prepare for plain morphing
+// this.value = from
+// this.destination = to
+// },
+//
+// extend: {
+// at: function (pos, real) {
+// return real < 1 ? this.value : this.destination
+// },
+//
+// valueOf: function () {
+// return this.value
+// }
+// }
+//
+// })
+//
+// SVG.extend(SVG.Timeline, {
+// // Add animatable attributes
+// attr: function (a, v, relative) {
+// // apply attributes individually
+// if (typeof a === 'object') {
+// for (var key in a) {
+// this.attr(key, a[key])
+// }
+// } else {
+// this.add(a, v, 'attrs')
+// }
+//
+// return this
+// },
+// // Add animatable styles
+// css: function (s, v) {
+// if (typeof s === 'object') {
+// for (var key in s) {
+// this.css(key, s[key])
+// }
+// } else {
+// this.add(s, v, 'styles')
+// }
+//
+// return this
+// },
+// // Animatable x-axis
+// x: function (x, relative) {
+// if (this.target() instanceof SVG.G) {
+// this.transform({x: x}, relative)
+// return this
+// }
+//
+// var num = new SVG.Number(x)
+// num.relative = relative
+// return this.add('x', num)
+// },
+// // Animatable y-axis
+// y: function (y, relative) {
+// if (this.target() instanceof SVG.G) {
+// this.transform({y: y}, relative)
+// return this
+// }
+//
+// var num = new SVG.Number(y)
+// num.relative = relative
+// return this.add('y', num)
+// },
+// // Animatable center x-axis
+// cx: function (x) {
+// return this.add('cx', new SVG.Number(x))
+// },
+// // Animatable center y-axis
+// cy: function (y) {
+// return this.add('cy', new SVG.Number(y))
+// },
+// // Add animatable move
+// move: function (x, y) {
+// return this.x(x).y(y)
+// },
+// // Add animatable center
+// center: function (x, y) {
+// return this.cx(x).cy(y)
+// },
+// // Add animatable size
+// size: function (width, height) {
+// if (this.target() instanceof SVG.Text) {
+// // animate font size for Text elements
+// this.attr('font-size', width)
+// } else {
+// // animate bbox based size for all other elements
+// var box
+//
+// if (!width || !height) {
+// box = this.target().bbox()
+// }
+//
+// if (!width) {
+// width = box.width / box.height * height
+// }
+//
+// if (!height) {
+// height = box.height / box.width * width
+// }
+//
+// this.add('width', new SVG.Number(width))
+// .add('height', new SVG.Number(height))
+// }
+//
+// return this
+// },
+// // Add animatable width
+// width: function (width) {
+// return this.add('width', new SVG.Number(width))
+// },
+// // Add animatable height
+// height: function (height) {
+// return this.add('height', new SVG.Number(height))
+// },
+// // Add animatable plot
+// plot: function (a, b, c, d) {
+// // Lines can be plotted with 4 arguments
+// if (arguments.length === 4) {
+// return this.plot([a, b, c, d])
+// }
+//
+// return this.add('plot', new (this.target().MorphArray)(a))
+// },
+// // Add leading method
+// leading: function (value) {
+// return this.target().leading
+// ? this.add('leading', new SVG.Number(value))
+// : this
+// },
+// // Add animatable viewbox
+// viewbox: function (x, y, width, height) {
+// if (this.target() instanceof SVG.Container) {
+// this.add('viewbox', new SVG.Box(x, y, width, height))
+// }
+//
+// return this
+// },
+// update: function (o) {
+// if (this.target() instanceof SVG.Stop) {
+// if (typeof o === 'number' || o instanceof SVG.Number) {
+// 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)
+// }
+//
+// return this
+// }
+// })
diff --git a/src/gradient.js b/src/gradient.js
index ea2197b..2f2a609 100644
--- a/src/gradient.js
+++ b/src/gradient.js
@@ -50,7 +50,7 @@ SVG.Gradient = SVG.invent({
})
// Add animatable methods to both gradient and fx module
-SVG.extend([SVG.Gradient, SVG.FX], {
+SVG.extend([SVG.Gradient, SVG.Timeline], {
// From position
from: function (x, y) {
return (this._target || this).type === 'radialGradient'
@@ -101,5 +101,4 @@ SVG.Stop = SVG.invent({
return this
}
}
-
})
diff --git a/src/matrix.js b/src/matrix.js
index 786d1c1..1649370 100644
--- a/src/matrix.js
+++ b/src/matrix.js
@@ -32,6 +32,13 @@ SVG.Matrix = SVG.invent({
// Transform a matrix into another matrix by manipulating the space
transform: function (o) {
+ // Check if o is a matrix and then left multiply it directly
+ if (o.a != null) {
+ var matrix = new SVG.Matrix(o)
+ var newMatrix = this.lmultiply(matrix)
+ return newMatrix
+ }
+
// Get all of the parameters required to form the matrix
var flipX = o.flip && (o.flip === 'x' || o.flip === 'both') ? -1 : 1
var flipY = o.flip && (o.flip === 'y' || o.flip === 'both') ? -1 : 1
diff --git a/src/queue.js b/src/queue.js
new file mode 100644
index 0000000..abcfb84
--- /dev/null
+++ b/src/queue.js
@@ -0,0 +1,81 @@
+SVG.Queue = SVG.invent({
+ create: function () {
+ this._first = null
+ this._last = null
+ this.length = 0
+ this.id = 0
+ },
+
+ extend: {
+ push: function (value) {
+
+ // An item stores an id and the provided value
+ var item = { id: this.id++, value: value }
+
+ // Deal with the queue being empty or populated
+ if (this._last) {
+ this._last = this._last.next = item
+ } else {
+ this._last = this._first = item
+ }
+
+ this.length++
+ },
+
+ shift: function () {
+ if (this.length == 0) {
+ return
+ }
+
+ var remove = this._first
+ this._first = remove.next
+ this._last = --this.length ? this._last : null
+ return remove.value
+ },
+
+ // Shows us the first item in the list
+ first: function () {
+ return this._first && this._first.value
+ },
+
+ // Shows us the last item in the list
+ last: function () {
+ return this._last && this._last.value
+ },
+
+ // Removes the first item from the front where matcher returns true
+ remove: function (matcher) {
+ // Find the first match
+ var previous = null
+ var current = this._first
+ while (current) {
+
+ // If we have a match, we are done
+ if (matcher(current)) break
+
+ // Otherwise, advance both of the pointers
+ previous = current
+ current = current.next
+ }
+
+ // If we got the first item, adjust the first pointer
+ if (current && current === this._first)
+ this._first = this._first.next
+
+ // If we got the last item, adjust the last pointer
+ if (current && current === this._last)
+ this._last = previous
+
+ // If we got an item, fix the list and return the item
+ if (current) {
+ --this.length
+
+ if (previous) {
+ previous.next = current.next
+ }
+
+ return current.item
+ }
+ }
+ }
+})
diff --git a/src/sugar.js b/src/sugar.js
index e3ed6a5..f7b7183 100644
--- a/src/sugar.js
+++ b/src/sugar.js
@@ -1,151 +1,151 @@
-// Define list of available attributes for stroke and fill
-var sugar = {
- stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'],
- fill: ['color', 'opacity', 'rule'],
- prefix: function (t, a) {
- return a === 'color' ? t : t + '-' + a
- }
-}
-
-// Add sugar for fill and stroke
-;['fill', 'stroke'].forEach(function (m) {
- var extension = {}
- var i
-
- extension[m] = function (o) {
- if (typeof o === 'undefined') {
- return this
- }
- if (typeof o === 'string' || SVG.Color.isRgb(o) || (o && typeof o.fill === 'function')) {
- this.attr(m, o)
- } else {
- // set all attributes from sugar.fill and sugar.stroke list
- for (i = sugar[m].length - 1; i >= 0; i--) {
- if (o[sugar[m][i]] != null) {
- this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]])
- }
- }
- }
-
- return this
- }
-
- SVG.extend([SVG.Element, SVG.FX], extension)
-})
-
-SVG.extend([SVG.Element, SVG.FX], {
- // Let the user set the matrix directly
- matrix: function (mat, b, c, d, e, f) {
- // Act as a getter
- if (mat == null) {
- return new SVG.Matrix(this)
- }
-
- // Act as a setter, the user can pass a matrix or a set of numbers
- return this.attr('transform', new SVG.Matrix(mat, b, c, d, e, f))
- },
-
- // Map rotation to transform
- rotate: function (angle, cx, cy) {
- return this.transform({rotate: angle, ox: cx, oy: cy}, true)
- },
-
- // Map skew to transform
- skew: function (x, y, cx, cy) {
- return arguments.length === 1 || arguments.length === 3
- ? this.transform({skew: x, ox: y, oy: cx}, true)
- : this.transform({skew: [x, y], ox: cx, oy: cy}, true)
- },
-
- shear: function (lam, cx, cy) {
- return this.transform({shear: lam, ox: cx, oy: cy}, true)
- },
-
- // Map scale to transform
- scale: function (x, y, cx, cy) {
- return arguments.length === 1 || arguments.length === 3
- ? this.transform({ scale: x, ox: y, oy: cx }, true)
- : this.transform({ scale: [x, y], ox: cx, oy: cy }, true)
- },
-
- // Map translate to transform
- translate: function (x, y) {
- return this.transform({ translate: [x, y] }, true)
- },
-
- // Map relative translations to transform
- relative: function (x, y) {
- return this.transform({ relative: [x, y] }, true)
- },
-
- // Map flip to transform
- flip: function (direction, around) {
- var directionString = typeof direction === 'string' ? direction
- : isFinite(direction) ? 'both'
- : 'both'
- var origin = (direction === 'both' && isFinite(around)) ? [around, around]
- : (direction === 'x') ? [around, 0]
- : (direction === 'y') ? [0, around]
- : isFinite(direction) ? [direction, direction]
- : [0, 0]
- this.transform({flip: directionString, origin: origin}, true)
- },
-
- // Opacity
- opacity: function (value) {
- return this.attr('opacity', value)
- },
-
- // Relative move over x axis
- dx: function (x) {
- return this.x(new SVG.Number(x).plus(this instanceof SVG.FX ? 0 : this.x()), true)
- },
-
- // Relative move over y axis
- dy: function (y) {
- return this.y(new SVG.Number(y).plus(this instanceof SVG.FX ? 0 : this.y()), true)
- },
-
- // Relative move over x and y axes
- dmove: function (x, y) {
- return this.dx(x).dy(y)
- }
-})
-
-SVG.extend([SVG.Rect, SVG.Ellipse, SVG.Circle, SVG.Gradient, SVG.FX], {
- // Add x and y radius
- radius: function (x, y) {
- var type = (this._target || this).type
- return type === 'radialGradient' || type === 'radialGradient'
- ? this.attr('r', new SVG.Number(x))
- : this.rx(x).ry(y == null ? x : y)
- }
-})
-
-SVG.extend(SVG.Path, {
- // Get path length
- length: function () {
- return this.node.getTotalLength()
- },
- // Get point at length
- pointAt: function (length) {
- return new SVG.Point(this.node.getPointAtLength(length))
- }
-})
-
-SVG.extend([SVG.Parent, SVG.Text, SVG.Tspan, SVG.FX], {
- // Set font
- font: function (a, v) {
- if (typeof a === 'object') {
- for (v in a) this.font(v, a[v])
- }
-
- return a === 'leading'
- ? this.leading(v)
- : a === 'anchor'
- ? this.attr('text-anchor', v)
- : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style'
- ? this.attr('font-' + a, v)
- : this.attr(a, v)
- }
-})
+// // Define list of available attributes for stroke and fill
+// var sugar = {
+// stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'],
+// fill: ['color', 'opacity', 'rule'],
+// prefix: function (t, a) {
+// return a === 'color' ? t : t + '-' + a
+// }
+// }
+//
+// // Add sugar for fill and stroke
+// ;['fill', 'stroke'].forEach(function (m) {
+// var extension = {}
+// var i
+//
+// extension[m] = function (o) {
+// if (typeof o === 'undefined') {
+// return this
+// }
+// if (typeof o === 'string' || SVG.Color.isRgb(o) || (o && typeof o.fill === 'function')) {
+// this.attr(m, o)
+// } else {
+// // set all attributes from sugar.fill and sugar.stroke list
+// for (i = sugar[m].length - 1; i >= 0; i--) {
+// if (o[sugar[m][i]] != null) {
+// this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]])
+// }
+// }
+// }
+//
+// return this
+// }
+//
+// SVG.extend([SVG.Element, SVG.Timeline], extension)
+// })
+//
+// SVG.extend([SVG.Element, SVG.Timeline], {
+// // Let the user set the matrix directly
+// matrix: function (mat, b, c, d, e, f) {
+// // Act as a getter
+// if (mat == null) {
+// return new SVG.Matrix(this)
+// }
+//
+// // Act as a setter, the user can pass a matrix or a set of numbers
+// return this.attr('transform', new SVG.Matrix(mat, b, c, d, e, f))
+// },
+//
+// // Map rotation to transform
+// rotate: function (angle, cx, cy) {
+// return this.transform({rotate: angle, ox: cx, oy: cy}, true)
+// },
+//
+// // Map skew to transform
+// skew: function (x, y, cx, cy) {
+// return arguments.length === 1 || arguments.length === 3
+// ? this.transform({skew: x, ox: y, oy: cx}, true)
+// : this.transform({skew: [x, y], ox: cx, oy: cy}, true)
+// },
+//
+// shear: function (lam, cx, cy) {
+// return this.transform({shear: lam, ox: cx, oy: cy}, true)
+// },
+//
+// // Map scale to transform
+// scale: function (x, y, cx, cy) {
+// return arguments.length === 1 || arguments.length === 3
+// ? this.transform({ scale: x, ox: y, oy: cx }, true)
+// : this.transform({ scale: [x, y], ox: cx, oy: cy }, true)
+// },
+//
+// // Map translate to transform
+// translate: function (x, y) {
+// return this.transform({ translate: [x, y] }, true)
+// },
+//
+// // Map relative translations to transform
+// relative: function (x, y) {
+// return this.transform({ relative: [x, y] }, true)
+// },
+//
+// // Map flip to transform
+// flip: function (direction, around) {
+// var directionString = typeof direction === 'string' ? direction
+// : isFinite(direction) ? 'both'
+// : 'both'
+// var origin = (direction === 'both' && isFinite(around)) ? [around, around]
+// : (direction === 'x') ? [around, 0]
+// : (direction === 'y') ? [0, around]
+// : isFinite(direction) ? [direction, direction]
+// : [0, 0]
+// this.transform({flip: directionString, origin: origin}, true)
+// },
+//
+// // Opacity
+// opacity: function (value) {
+// return this.attr('opacity', value)
+// },
+//
+// // Relative move over x axis
+// dx: function (x) {
+// return this.x(new SVG.Number(x).plus(this instanceof SVG.Timeline ? 0 : this.x()), true)
+// },
+//
+// // Relative move over y axis
+// dy: function (y) {
+// return this.y(new SVG.Number(y).plus(this instanceof SVG.Timeline ? 0 : this.y()), true)
+// },
+//
+// // Relative move over x and y axes
+// dmove: function (x, y) {
+// return this.dx(x).dy(y)
+// }
+// })
+//
+// SVG.extend([SVG.Rect, SVG.Ellipse, SVG.Circle, SVG.Gradient, SVG.Timeline], {
+// // Add x and y radius
+// radius: function (x, y) {
+// var type = (this._target || this).type
+// return type === 'radialGradient' || type === 'radialGradient'
+// ? this.attr('r', new SVG.Number(x))
+// : this.rx(x).ry(y == null ? x : y)
+// }
+// })
+//
+// SVG.extend(SVG.Path, {
+// // Get path length
+// length: function () {
+// return this.node.getTotalLength()
+// },
+// // Get point at length
+// pointAt: function (length) {
+// return new SVG.Point(this.node.getPointAtLength(length))
+// }
+// })
+//
+// SVG.extend([SVG.Parent, SVG.Text, SVG.Tspan, SVG.Timeline], {
+// // Set font
+// font: function (a, v) {
+// if (typeof a === 'object') {
+// for (v in a) this.font(v, a[v])
+// }
+//
+// return a === 'leading'
+// ? this.leading(v)
+// : a === 'anchor'
+// ? this.attr('text-anchor', v)
+// : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style'
+// ? this.attr('font-' + a, v)
+// : this.attr(a, v)
+// }
+// })
diff --git a/src/timeline.js b/src/timeline.js
new file mode 100644
index 0000000..035c0f7
--- /dev/null
+++ b/src/timeline.js
@@ -0,0 +1,171 @@
+
+// Must Change ....
+SVG.easing = {
+ '-': function (pos) { return pos },
+ '<>': function (pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5 },
+ '>': function (pos) { return Math.sin(pos * Math.PI / 2) },
+ '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 }
+}
+
+
+function Runner (timeline) {
+
+ // We store a reference to the function to run and the timeline to use
+ this.functions = []
+ this.timeline = timeline
+ this.transforms = []
+ this.done = false
+
+ // We copy the current values from the timeline because they can change
+ this._startTime = timeline._startTime
+ this._duration = timeline._duration
+ this._loop = timeline._loop
+}
+
+Runner.prototype = {
+
+ add: function (initFn, runFn) {
+ this.initialisers.push(initFn)
+ this.functions.push(fn)
+ },
+
+ run: function (time) {
+
+ var line = this.timeline
+
+ // If it is time to do something, act now.
+ var running = this._start < time && time < end
+ if (running && this._running) {
+ var position = (time - this._startTime) / this._duration
+ var toRun = this.functions
+ for (var i = 0, len = toRun.length, i < len ; ++i) {
+ toRun[i](position)
+ }
+ }
+
+ // If we are not paused or stopped, request another frame
+ if (this._running) SVG.Animator.frame(closure, this._startTime)
+
+ // Tell the caller whether this animation is finished
+ closure.finished = !running
+ },
+
+ stop: function () {
+
+ },
+
+ pause: function () {
+
+ },
+}
+
+
+SVG.Timeline = SVG.invent({
+
+ create: function (o, easy, delay, epoch) {
+
+ this.baseTransform = []
+ this.runners = []
+ this.controller = null
+
+ if(o instanceof 'function') {
+ this.controller = o
+
+ } else if (typeof o === 'object') {
+ ease = o.ease
+ delay = o.delay
+ o = o.duration
+ }
+
+ this.ease = ease
+ this.delay = delay
+ this.duration = o
+ },
+
+ extend: {
+
+ animate (duration, ease, delay, epoch)
+ loop (times, reverse)
+ duration (time)
+ delay (by, epoch)
+ ease (fn)
+
+ play ()
+ pause ()
+ stop ()
+ finish (all=true)
+ speed (newSpeed)
+ seek (dt)
+ persist (dt || forever) // 0 by default
+ reverse ()
+
+ _step (dt) {
+
+ },
+
+ // Checks if we are running and continues the animation
+ _continue () {
+ , continue: function () {
+ if (this.paused) return
+ if (!this.nextFrame)
+ this.step()
+ return this
+ }
+
+ }
+ },
+
+
+ construct: {
+ animate: function(o, ease, delay, epoch) {
+ return (this.timeline = this.timeline || new SVG.Timeline(o, ease, delay, epoch))
+ }
+ }
+
+}
+
+// Extend the attribute methods separately to avoid cluttering the main
+// Timeline class above
+SVG.extend(SVG.Timeline, {
+
+
+ attr: function (a, v) {
+ return this.styleAttr('attr', a, v)
+ },
+
+ // Add animatable styles
+ css: function (s, v) {
+ return this.styleAttr('css', s, v)
+ },
+
+ styleAttr (type, name, val) {
+ // apply attributes individually
+ if (typeof name === 'object') {
+ for (var key in val) {
+ this.styleAttr(type, key, val[key])
+ }
+ }
+
+ var morpher = new Morph(this.controller).to(val)
+
+ this.queue(
+ function () {
+ morpher = morpher.from(element[type]('name'))
+ },
+ function () {
+ this.element[type](name, morpher.at(pos))
+ }
+ )
+
+ return this
+ },
+
+ zoom(level, point) {
+ let morpher = SVG.Number(level).controller(this.controller)
+ this.queue(
+ () => {morpher = morpher.from(element.zoom())},
+ (pos) => {element.zoom(morpher.at(pos), point)}
+ )
+ return this
+ }
+})
diff --git a/src/transform.js b/src/transform.js
index b173cb2..ecb5fc4 100644
--- a/src/transform.js
+++ b/src/transform.js
@@ -50,7 +50,8 @@ SVG.extend(SVG.Element, {
SVG.extend(SVG.Element, {
// Add transformations
- transform: function (o, cyOrRel) {
+ transform: function (o, relative) {
+
// Get the bounding box of the element with no transformations applied
var bbox = this.bbox()
@@ -59,20 +60,6 @@ SVG.extend(SVG.Element, {
var decomposed = new SVG.Matrix(this).decompose()
return decomposed[o] || decomposed
- // Let the user pass in a matrix as well
- } else if (o.a != null) {
- // Construct a matrix from the first parameter
- var matrix = new SVG.Matrix(o)
-
- // If we have a relative matrix, we just apply the old matrix
- if (cyOrRel != null) {
- var oldMatrix = new SVG.Matrix(this)
- matrix = matrix.multiply(oldMatrix)
- }
-
- // Apply the matrix directly
- return this.attr('transform', matrix)
-
// Allow the user to define the origin with a string
} else if (typeof o.origin === 'string' ||
(o.origin == null && o.ox == null && o.oy == null)
@@ -99,13 +86,14 @@ SVG.extend(SVG.Element, {
}
// The user can pass a boolean, an SVG.Element or an SVG.Matrix or nothing
- var result = new SVG.Matrix(cyOrRel === true ? this : cyOrRel).transform(o)
+ var cleanRelative = relative === true ? this : (relative || false)
+ var result = new SVG.Matrix(cleanRelative).transform(o)
return this.attr('transform', result)
}
})
-SVG.extend(SVG.FX, {
- transform: function (o, relative) {
+SVG.extend(SVG.Timeline, {
+ transform: function (o, relative, affine) {
// // get target in case of the fx module, otherwise reference this
// var target = this.target()
@@ -232,146 +220,3 @@ SVG.extend(SVG.FX, {
// return this._callStart()
}
})
-
-// TODO: DESTROY
-// =======
-//
-//
-// SVG.Transformation = SVG.invent({
-//
-// create: function(source, inversed){
-//
-// if(arguments.length > 1 && typeof inversed != 'boolean'){
-// return this.constructor.call(this, [].slice.call(arguments))
-// }
-//
-// if(Array.isArray(source)){
-// for(var i = 0, len = this.arguments.length; i < len; ++i){
-// this[this.arguments[i]] = source[i]
-// }
-// } else if(typeof source == 'object'){
-// for(var i = 0, len = this.arguments.length; i < len; ++i){
-// this[this.arguments[i]] = source[this.arguments[i]]
-// }
-// }
-//
-// this.inversed = false
-//
-// if(inversed === true){
-// this.inversed = true
-// }
-//
-// }
-//
-// , extend: {
-//
-// arguments: []
-// , method: ''
-//
-// , at: function(pos){
-//
-// var params = []
-//
-// for(var i = 0, len = this.arguments.length; i < len; ++i){
-// params.push(this[this.arguments[i]])
-// }
-//
-// var m = this._undo || new SVG.Matrix()
-//
-// m = new SVG.Matrix().morph(SVG.Matrix.prototype[this.method].apply(m, params)).at(pos)
-//
-// return this.inversed ? m.inverse() : m
-//
-// }
-//
-// , undo: function(o){
-// for(var i = 0, len = this.arguments.length; i < len; ++i){
-// o[this.arguments[i]] = typeof this[this.arguments[i]] == 'undefined' ? 0 : o[this.arguments[i]]
-// }
-//
-// // The method SVG.Matrix.extract which was used before calling this
-// // method to obtain a value for the parameter o doesn't return a cx and
-// // a cy so we use the ones that were provided to this object at its creation
-// o.cx = this.cx
-// o.cy = this.cy
-//
-// this._undo = new SVG[capitalize(this.method)](o, true).at(1)
-//
-// return this
-// }
-//
-// }
-//
-// })
-//
-// SVG.Translate = SVG.invent({
-//
-// parent: SVG.Matrix
-// , inherit: SVG.Transformation
-//
-// , create: function(source, inversed){
-// this.constructor.apply(this, [].slice.call(arguments))
-// }
-//
-// , extend: {
-// arguments: ['transformedX', 'transformedY']
-// , method: 'translate'
-// }
-//
-// })
-//
-// SVG.Rotate = SVG.invent({
-//
-// parent: SVG.Matrix
-// , inherit: SVG.Transformation
-//
-// , create: function(source, inversed){
-// this.constructor.apply(this, [].slice.call(arguments))
-// }
-//
-// , extend: {
-// arguments: ['rotation', 'cx', 'cy']
-// , method: 'rotate'
-// , at: function(pos){
-// var m = new SVG.Matrix().rotate(new SVG.Number().morph(this.rotation - (this._undo ? this._undo.rotation : 0)).at(pos), this.cx, this.cy)
-// return this.inversed ? m.inverse() : m
-// }
-// , undo: function(o){
-// this._undo = o
-// return this
-// }
-// }
-//
-// })
-//
-// SVG.Scale = SVG.invent({
-//
-// parent: SVG.Matrix
-// , inherit: SVG.Transformation
-//
-// , create: function(source, inversed){
-// this.constructor.apply(this, [].slice.call(arguments))
-// }
-//
-// , extend: {
-// arguments: ['scaleX', 'scaleY', 'cx', 'cy']
-// , method: 'scale'
-// }
-//
-// })
-//
-// SVG.Skew = SVG.invent({
-//
-// parent: SVG.Matrix
-// , inherit: SVG.Transformation
-//
-// , create: function(source, inversed){
-// this.constructor.apply(this, [].slice.call(arguments))
-// }
-//
-// , extend: {
-// arguments: ['skewX', 'skewY', 'cx', 'cy']
-// , method: 'skew'
-// }
-//
-// })