aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md5
-rw-r--r--README.md8
-rw-r--r--dist/svg.js372
-rw-r--r--dist/svg.min.js4
-rw-r--r--playgrounds/transforms/transforms.html18
-rw-r--r--playgrounds/transforms/transforms.js21
-rw-r--r--spec/SpecRunner.html16
-rw-r--r--spec/spec/element.js51
-rw-r--r--spec/spec/helper.js12
-rw-r--r--spec/spec/matrix.js256
-rw-r--r--src/boxes.js19
-rw-r--r--src/helpers.js14
-rw-r--r--src/line.js3
-rw-r--r--src/matrix.js232
-rw-r--r--src/point.js8
-rw-r--r--src/sugar.js33
-rw-r--r--src/transform.js68
17 files changed, 626 insertions, 514 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ebbc678..e0ee5cb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,8 @@ The document follows the conventions described in [“Keep a CHANGELOG”](http:
- added `SVG.HTMLNode` which is the object wrapped around html nodes to put something in them
- added `random` option and `randomize()` method to `SVG.Color` -> __TODO!__
- added `precision()` method to round numeric element attributes -> __TODO!__
+- added a linter during the npm build process
+- added `npm build:dev` to let you develop without getting too annoyed
### Removed
- removed `SVG.Array.split()` function
@@ -59,6 +61,9 @@ The document follows the conventions described in [“Keep a CHANGELOG”](http:
- SVG.Elements constructor now tries to import svgjs:data from the node
- `SVG.on()` calls the listener in the context of the passed object. el.on always uses the svg.js object as context
- `SVG.on()` and `el.on()` now accepts multiple comma or space seperated events e.g. "mousedown, foo bar" (#727)
+- Matrices now apply transformations like `scale`, `translate`, etc... by left multiplying them to simplify transformations
+- Transforming an element is now much simpler
+-
### Fixed
- fixed a bug in clipping and masking where empty nodes persists after removal -> __TODO!__
diff --git a/README.md b/README.md
index d0d7fdf..ce9c65e 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,14 @@ However, because we were too nice to put you through the pain of always having t
This will only warn you about linting errors and give you useful feedback about possible errors you may have in your code (but this is no substitute for tests). Please make sure that **before making any pull requests**, you pass all of our tests and can build with `npm run build` first.
+> ⚠️⚠️⚠️ WARNING ⚠️⚠️⚠️
+> This library still uses es5, so if you do anything like using `let`, it will
+> probably break, and you probably won't be able to figure out why. This is
+> only a temporary trouble 🙃 We will fix it as soon as we can!
+>
+> The linter is ready for es6, but the build process is not, so if you get an
+> error and the linter says nothing; check for es6iness 😍
+
### Testing
This will set up everything. While you are working, you should make sure your changes pass all of our tests, so just run:
diff --git a/dist/svg.js b/dist/svg.js
index 9815673..77f8721 100644
--- a/dist/svg.js
+++ b/dist/svg.js
@@ -6,7 +6,7 @@
* @copyright Wout Fierens <wout@mick-wout.com>
* @license MIT
*
-* BUILT: Tue Feb 27 2018 17:22:06 GMT+1100 (AEDT)
+* BUILT: Fri Mar 02 2018 11:37:53 GMT+1100 (AEDT)
*/;
(function(root, factory) {
@@ -2236,6 +2236,35 @@ SVG.extend(SVG.FX, {
/* global abcdef, arrayToMatrix, parseMatrix, unitCircle, mag */
+// Produce a matrix from affine parameters
+SVG.compose = function (o, cx, cy) {
+ // Set the defaults
+ var tx = o.translateX || 0
+ var ty = o.translateY || 0
+ var theta = o.theta || 0
+ var sx = o.scaleX || 1
+ var sy = o.scaleY || 1
+ var lam = o.shear || 0
+ cx = cx || 0
+ cy = cy || 0
+
+ // Calculate the trigonometric values
+ var ct = Math.cos(theta * Math.PI / 180)
+ var st = Math.sin(theta * Math.PI / 180)
+
+ // Calculate the matrix components directly
+ var a = sx * ct
+ var b = sx * st
+ var c = lam * sx * ct - sy * st
+ var d = lam * sx * st + sy * ct
+ var e = -sx * ct * (cx + cy * lam) + sy * st * cy + tx + cx
+ var f = -sx * st * (cx + cy * lam) - sy * ct * cy + ty + cy
+
+ // Construct a new matrix and return it
+ var matrix = new SVG.Matrix([a, b, c, d, e, f])
+ return matrix
+}
+
SVG.Matrix = SVG.invent({
// Initialize
create: function (source) {
@@ -2261,43 +2290,19 @@ SVG.Matrix = SVG.invent({
// Add methods
extend: {
- // Convert an object of affine parameters into a matrix
- compose: function (o, cx, cy) {
- // Set the defaults
- var tx = o.translateX || 0
- var ty = o.translateY || 0
- var theta = o.theta || 0
- var sx = o.scaleX || 1
- var sy = o.scaleY || 1
- var lam = o.shear || 0
+ // Decompose a matrix into the affine parameters needed to form it
+ decompose: function (cx, cy) {
+ // Choose a default center point
cx = cx || 0
cy = cy || 0
- // Calculate the trigonometric values
- var ct = Math.cos(theta * Math.PI / 180)
- var st = Math.sin(theta * Math.PI / 180)
-
- // Calculate the matrix components directly
- var a = sx * ct
- var b = sx * st
- var c = lam * sx * ct - sy * st
- var d = lam * sx * st + sy * ct
- var e = -sx * ct * (cx + cy * lam) + sy * st * cy + tx + cx
- var f = -sx * st * (cx + cy * lam) - sy * ct * cy + ty + cy
-
- // Construct a new matrix and return it
- var matrix = new SVG.Matrix([a, b, c, d, e, f])
- return matrix
- },
- // Decompose a matrix into the affine parameters needed to form it
- decompose: function (matrix, cx, cy) {
// Get the paramaters of the current matrix
- var a = matrix.a
- var b = matrix.b
- var c = matrix.c
- var d = matrix.d
- var e = matrix.e
- var f = matrix.f
+ var a = this.a
+ var b = this.b
+ var c = this.c
+ var d = this.d
+ var e = this.e
+ var f = this.f
// Project the first basis vector onto the unit circle
var circle = unitCircle(a, b)
@@ -2319,7 +2324,7 @@ SVG.Matrix = SVG.invent({
// Bundle the affine parameters
translateX: tx,
translateY: ty,
- theta: theta,
+ rotate: theta,
scaleX: sx,
scaleY: sy,
shear: lam,
@@ -2338,60 +2343,72 @@ SVG.Matrix = SVG.invent({
matrix: new SVG.Matrix(this)
}
},
+
// Clone matrix
- form: function (o) {
+ affine: function (o) {
// 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
- var skewX = o.skew.length ? o.skew[0]
+ var skewX = o.skew && o.skew.length ? o.skew[0]
: isFinite(o.skew) ? o.skew
: isFinite(o.skewX) ? o.skewX
: 0
- var skewY = o.skew.length ? o.skew[1]
+ var skewY = o.skew && o.skew.length ? o.skew[1]
: isFinite(o.skew) ? o.skew
: isFinite(o.skewY) ? o.skewY
: 0
- var sx = o.scale.length ? o.scale[0] * flipX
+ var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX
: isFinite(o.scale) ? o.scale * flipX
: isFinite(o.scaleX) ? o.scaleX * flipX
: flipX
- var sy = o.scale.length ? o.scale[1] * flipY
+ var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY
: isFinite(o.scale) ? o.scale * flipY
: isFinite(o.scaleY) ? o.scaleY * flipY
: flipY
- var kx = Math.tan(SVG.utils.radians(skewX))
- var ky = Math.tan(SVG.utils.radians(skewY))
- var lam = o.shear || 0
- var theta = SVG.utils.radians(o.rotate || 0)
- var st = Math.sin(theta)
- var ct = Math.cos(theta)
- var ox = o.origin.length ? o.origin[0] : o.ox || 0
- var oy = o.origin.length ? o.origin[1] : o.oy || 0
- var px = o.position.length ? o.position[0] : o.px || ox
- var py = o.position.length ? o.position[1] : o.py || oy
- var tx = o.translate.length ? o.translate[0] : o.tx || 0
- var ty = o.translate.length ? o.translate[1] : o.ty || 0
-
- // Form the matrix parameters... aka. welcome to wonderland! (used wolfram)
- var a = ct * sx + ky * st * sy
- var b = ct * ky * sy - st * sx
- var c = ct * kx * sx + st * sy + lam * (ct * sx + ky * st * sy)
- var d = -kx * st * sx + ct * sy + lam * (-st * sx + ct * ky * sy)
- var e = px + tx + ox * (ct * sx + ky * st * sy) + oy * (ct * kx * sx + st * sy + lam * (ct * sx + ky * st * sy))
- var f = py + ty + ox * (-st * sx + ct * ky * sy) + oy * (-kx * st * sx + ct * sy + lam * (-st * sx + ct * ky * sy))
- var result = new SVG.Matrix(a, b, c, d, e, f)
- return result
+ var shear = o.shear || 0
+ var theta = o.rotate || 0
+ var ox = o.origin && o.origin.length ? o.origin[0] : o.ox || 0
+ var oy = o.origin && o.origin.length ? o.origin[1] : o.oy || 0
+ var px = o.position && o.position.length ? o.position[0] : o.px
+ var py = o.position && o.position.length ? o.position[1] : o.py
+ var tx = o.translate && o.translate.length ? o.translate[0] : o.tx || 0
+ var ty = o.translate && o.translate.length ? o.translate[1] : o.ty || 0
+
+ // Construct the resulting matrix
+ var transformer = new SVG.Matrix()
+ .translate(-ox, -oy)
+ .scale(scaleX, scaleY)
+ .skew(skewX, skewY)
+ .shear(shear)
+ .rotate(theta)
+ .translate(ox, oy)
+ .translate(tx, ty)
+ .lmultiply(new SVG.Matrix(this))
+
+ // If we want the origin at a particular place, we force it there
+ if (isFinite(px) && isFinite(py)) {
+ // Figure out where the origin went and the delta to get there
+ var p = new SVG.Point(ox - tx, oy - ty).transform(transformer)
+ var dx = px - p.x
+ var dy = py - p.y
+
+ // Apply another translation
+ transformer = transformer.translate(dx, dy)
+ }
+ return transformer
},
+
clone: function () {
return new SVG.Matrix(this)
},
+
// Morph one matrix into another
morph: function (matrix) {
// store new destination
this.destination = new SVG.Matrix(matrix)
-
return this
},
+
// Get morphed matrix at a given position
at: function (pos) {
// make sure a destination is defined
@@ -2409,20 +2426,44 @@ SVG.Matrix = SVG.invent({
return matrix
},
- // Multiplies by given matrix
+
+ // Left multiplies by the given matrix
multiply: function (matrix) {
- return new SVG.Matrix(this.native().multiply(parseMatrix(matrix).native()))
+ // Get the matrices
+ var l = this
+ var r = parseMatrix(matrix)
+
+ // Work out the product directly
+ var a = l.a * r.a + l.c * r.b
+ var b = l.b * r.a + l.d * r.b
+ var c = l.a * r.c + l.c * r.d
+ var d = l.b * r.c + l.d * r.d
+ var e = l.e + l.a * r.e + l.c * r.f
+ var f = l.f + l.b * r.e + l.d * r.f
+
+ // Form the matrix and return it
+ var product = new SVG.Matrix(a, b, c, d, e, f)
+ return product
},
+
+ lmultiply: function (matrix) {
+ var l = parseMatrix(matrix)
+ return l.multiply(this)
+ },
+
// Inverses matrix
inverse: function () {
return new SVG.Matrix(this.native().inverse())
},
+
// Translate matrix
translate: function (x, y) {
- var translation = new SVG.Matrix(this.native().translate(x || 0, y || 0))
- var matrix = this.multiply(translation)
- return matrix
+ var translation = new SVG.Matrix(this)
+ translation.e += x || 0
+ translation.f += y || 0
+ return translation
},
+
// Scale matrix
scale: function (x, y, cx, cy) {
// Support uniform scaling
@@ -2436,10 +2477,10 @@ SVG.Matrix = SVG.invent({
// Rotate the current matrix
var scale = new SVG.Matrix(x, 0, 0, y, 0, 0)
- var centered = this.around(cx, cy, scale)
- var matrix = this.multiply(centered)
+ var matrix = this.around(cx, cy, scale)
return matrix
},
+
// Rotate matrix
rotate: function (r, cx, cy) {
// Convert degrees to radians
@@ -2447,23 +2488,25 @@ SVG.Matrix = SVG.invent({
// Construct the rotation matrix
var rotation = new SVG.Matrix(Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0)
- var centered = this.around(cx, cy, rotation)
- var matrix = this.multiply(centered)
+ var matrix = this.around(cx, cy, rotation)
return matrix
},
+
// Flip matrix on x or y, at a given offset
- flip: function (a, o) {
- return a === 'x' ? this.scale(-1, 1, o, 0)
- : a === 'y' ? this.scale(1, -1, 0, o)
- : this.scale(-1, -1, a, o != null ? o : a)
+ flip: function (axis, around) {
+ return axis === 'x' ? this.scale(-1, 1, around, 0)
+ : axis === 'y' ? this.scale(1, -1, 0, around)
+ : this.scale(-1, -1, axis, around || axis) // Define an x, y flip point
},
- // Skew
+
+ // Shear matrix
shear: function (a, cx, cy) {
var shear = new SVG.Matrix(1, a, 0, 1, 0, 0)
- var centered = this.around(cx, cy, shear)
- var matrix = this.multiply(centered)
+ var matrix = this.around(cx, cy, shear)
return matrix
},
+
+ // Skew Matrix
skew: function (x, y, cx, cy) {
// support uniformal skew
if (arguments.length === 1) {
@@ -2480,25 +2523,27 @@ SVG.Matrix = SVG.invent({
// Construct the matrix
var skew = new SVG.Matrix(1, Math.tan(y), Math.tan(x), 1, 0, 0)
- var centered = this.around(cx, cy, skew)
- var matrix = this.multiply(centered)
+ var matrix = this.around(cx, cy, skew)
return matrix
},
+
// SkewX
skewX: function (x, cx, cy) {
return this.skew(x, 0, cx, cy)
},
+
// SkewY
skewY: function (y, cx, cy) {
return this.skew(0, y, cx, cy)
},
+
// Transform around a center point
around: function (cx, cy, matrix) {
- return this
- .multiply(new SVG.Matrix(1, 0, 0, 1, cx || 0, cy || 0))
- .multiply(matrix)
- .multiply(new SVG.Matrix(1, 0, 0, 1, -cx || 0, -cy || 0))
+ var dx = cx || 0
+ var dy = cy || 0
+ return this.translate(-dx, -dy).lmultiply(matrix).translate(dx, dy)
},
+
// Convert to native SVGMatrix
native: function () {
// create new matrix
@@ -2511,6 +2556,18 @@ SVG.Matrix = SVG.invent({
return matrix
},
+
+ // Check if two matrices are equal
+ equals: function (other) {
+ var comp = parseMatrix(other)
+ return closeEnough(this.a, comp.a)
+ && closeEnough(this.b, comp.b)
+ && closeEnough(this.c, comp.c)
+ && closeEnough(this.d, comp.d)
+ && closeEnough(this.e, comp.e)
+ && closeEnough(this.f, comp.f)
+ },
+
// Convert matrix to string
toString: function () {
return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'
@@ -2567,13 +2624,14 @@ SVG.Point = SVG.invent({
clone: function () {
return new SVG.Point(this)
},
+
// Morph one point into another
morph: function (x, y) {
// store new destination
this.destination = new SVG.Point(x, y)
-
return this
},
+
// Get morphed point at a given position
at: function (pos) {
// make sure a destination is defined
@@ -2584,9 +2642,9 @@ SVG.Point = SVG.invent({
x: this.x + (this.destination.x - this.x) * pos,
y: this.y + (this.destination.y - this.y) * pos
})
-
return point
},
+
// Convert to native SVGPoint
native: function () {
// create new point
@@ -2595,9 +2653,9 @@ SVG.Point = SVG.invent({
// update with current values
point.x = this.x
point.y = this.y
-
return point
},
+
// transform point with matrix
transform: function (matrix) {
return new SVG.Point(this.native().matrixTransform(matrix.native()))
@@ -2611,7 +2669,6 @@ SVG.extend(SVG.Element, {
point: function (x, y) {
return new SVG.Point(x, y).transform(this.screenCTM().inverse())
}
-
})
SVG.extend(SVG.Element, {
@@ -2702,11 +2759,16 @@ SVG.extend(SVG.Element, {
.split(SVG.regex.transforms).slice(0, -1).map(function (str) {
// generate key => value pairs
var kv = str.trim().split('(')
- return [kv[0], kv[1].split(SVG.regex.delimiter).map(function (str) { return parseFloat(str) })]
+ return [kv[0],
+ kv[1].split(SVG.regex.delimiter)
+ .map(function (str) { return parseFloat(str) })
+ ]
})
+ .reverse()
// merge every transformation into one matrix
.reduce(function (matrix, transform) {
- if (transform[0] === 'matrix') return matrix.multiply(arrayToMatrix(transform[1]))
+ if (transform[0] === 'matrix')
+ return matrix.lmultiply(arrayToMatrix(transform[1]))
return matrix[transform[0]].apply(matrix, transform[1])
}, new SVG.Matrix())
@@ -2733,22 +2795,40 @@ SVG.extend(SVG.Element, {
SVG.extend(SVG.Element, {
// Add transformations
- transform: function (o) {
+ transform: function (o, cyOrRel) {
+ // Get the bounding box of the element with no transformations applied
+ var bbox = this.bbox()
+
// Act as a getter if no object was passed
- if (typeof o !== 'object') {
- var matrix = new SVG.Matrix(this).decompose()
- return typeof o === 'string' ? matrix[o] : matrix
- }
+ if (o == null) {
+ return new SVG.Matrix(this)
+
+ // Let the user
+ } 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
- if (typeof o.origin === 'string') {
+ } else if (typeof o.origin === 'string'
+ || (o.origin == null && o.ox == null && o.oy == null)) {
// Get the bounding box and string to use in our calculations
- var string = o.origin.toLowerCase().trim()
- var bbox = this.bbox()
+ var string = typeof o.origin === 'string'
+ ? o.origin.toLowerCase().trim()
+ : 'center' // We want the center by default
+ var height = bbox.height
+ var width = bbox.width
var x = bbox.x
var y = bbox.y
- var width = bbox.width
- var height = bbox.height
// Set the bounds eg : "bottom-left", "Top right", "middle" etc...
o.ox = string.includes('left') ? x
@@ -2762,28 +2842,13 @@ SVG.extend(SVG.Element, {
o.origin = null
}
- // Get the resulting matrix and apply it to the element
- var result = new SVG.Matrix().form(o)
+ // The user can pass a boolean, an SVG.Element or an SVG.Matrix or nothing
+ var result = new SVG.Matrix(cyOrRel === true ? this : cyOrRel).affine(o)
var matrixString = result.toString()
- // Apply the result
+ // Apply the result directly to this matrix
return this.attr('transform', matrixString)
},
-
- // Map matrix to transform
- matrix: function (m, relative) {
- // Construct a matrix from the first parameter
- var matrix = new SVG.Matrix(m)
-
- // If we have a relative matrix, we just apply the old matrix
- if (relative) {
- var oldMatrix = new SVG.Matrix(this)
- matrix = oldMatrix.multiply(matrix)
- }
-
- // Apply the matrix directly
- return this.attr('transform', matrix)
- }
})
SVG.extend(SVG.FX, {
@@ -4082,6 +4147,7 @@ SVG.Line = SVG.invent({
[ this.attr('x2'), this.attr('y2') ]
])
},
+
// Overwrite native plot() method
plot: function (x1, y1, x2, y2) {
if (x1 == null) {
@@ -4094,10 +4160,12 @@ SVG.Line = SVG.invent({
return this.attr(x1)
},
+
// Move by left top corner
move: function (x, y) {
return this.attr(this.array().move(x, y).toLine())
},
+
// Set element size to given width and height
size: function (width, height) {
var p = proportionalSize(this, width, height)
@@ -4828,43 +4896,52 @@ var sugar = {
SVG.extend([SVG.Element, SVG.FX], {
// Map rotation to transform
rotate: function (angle, cx, cy) {
- var matrix = new SVG.Matrix().rotate(angle, cx, cy)
- return this.matrix(matrix, true)
+ return this.transform({rotate: angle, ox: cx, oy: cy}, true)
},
+
// Map skew to transform
skew: function (x, y, cx, cy) {
- var matrix = arguments.length === 1 || arguments.length === 3
- ? new SVG.Matrix().skew(x, x, cx, cy)
- : new SVG.Matrix().skew(x, y, cx, cy)
- return this.matrix(matrix, true)
+ 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)
},
+
// Map scale to transform
scale: function (x, y, cx, cy) {
return arguments.length === 1 || arguments.length === 3
- ? this.transform({ scale: x, cx: y, cy: cx })
- : this.transform({ scaleX: x, scaleY: y, cx: cx, cy: cy })
+ ? this.transform({ scale: x, origin: [y, cx] }, true)
+ : this.transform({ scaleX: x, scaleY: y, origin: [cx, cy] }, true)
},
+
// Map translate to transform
translate: function (x, y) {
- return this.transform({ x: x, y: y })
+ return this.transform({ translate: [x, y] }, true)
},
+
// Map flip to transform
- flip: function (a, o) {
- o = typeof a === 'number' ? a : o
- return this.transform({ flip: a || 'both', offset: o })
+ flip: function (direction, around) {
+ var origin = (direction === "both" && isFinite(around)) ? [around, around]
+ : (direction === "x") ? [around, 0]
+ : (direction === "y") ? [0, around]
+ : undefined
+ this.transform({flip: direction, origin: origin})
},
+
// 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)
@@ -5224,11 +5301,15 @@ function mag (a, b) {
// Given a coordinate (a, b), this will calculate the sin, cosine and angle
// of this point projected onto the unit circle directly
function unitCircle (a, b) {
- var len = Math.sqrt(a * a + b * b)
- var cos = a / len
- var sin = b / len
- var theta = Math.atan2(b, a) * 180 / Math.PI
- return {theta: theta, cos: cos, sin: sin}
+ var thetaRad = Math.atan2(b, a)
+ var thetaDeg = thetaRad * 180 / Math.PI
+ var cos = Math.cos(thetaRad)
+ var sin = Math.sin(thetaRad)
+ return {theta: thetaDeg, cos: cos, sin: sin}
+}
+
+function closeEnough (a, b, threshold) {
+ return Math.abs (b - a) < (threshold || 1e-6)
}
/* globals fullBox, domContains, isNulledBox, Exception */
@@ -5251,6 +5332,7 @@ SVG.Box = SVG.invent({
// add center, right, bottom...
fullBox(this)
},
+
extend: {
// Merge rect box with another, return a new instance
merge: function (box) {
@@ -5285,11 +5367,7 @@ SVG.Box = SVG.invent({
yMax = Math.max(yMax, p.y)
})
- return new SVG.Box(
- xMin, yMin,
- xMax - xMin,
- yMax - yMin
- )
+ return new SVG.Box(xMin, yMin, xMax - xMin, yMax - yMin)
},
addOffset: function () {
@@ -5298,9 +5376,11 @@ SVG.Box = SVG.invent({
this.y += window.pageYOffset
return this
},
+
toString: function () {
return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height
},
+
morph: function (x, y, width, height) {
this.destination = new SVG.Box(x, y, width, height)
return this
@@ -5310,15 +5390,15 @@ SVG.Box = SVG.invent({
if (!this.destination) return this
return new SVG.Box(
- this.x + (this.destination.x - this.x) * pos
- , this.y + (this.destination.y - this.y) * pos
- , this.width + (this.destination.width - this.width) * pos
- , this.height + (this.destination.height - this.height) * pos
+ this.x + (this.destination.x - this.x) * pos,
+ this.y + (this.destination.y - this.y) * pos,
+ this.width + (this.destination.width - this.width) * pos,
+ this.height + (this.destination.height - this.height) * pos
)
}
},
- // Define Parent
+ // Define Parent
parent: SVG.Element,
// Constructor
diff --git a/dist/svg.min.js b/dist/svg.min.js
index 2d6360d..30171f0 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 P.Element)return t;if("object"==typeof t)return P.adopt(t);if(null==t)return new P.Doc;if("string"==typeof t&&"<"!==t.charAt(0))return P.adopt(e.querySelector(t));var i=P.create("svg");return i.innerHTML=t,t=P.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(P.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){return t instanceof P.Matrix||(t=new P.Matrix(t)),t}function x(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 v(t){for(var e=t.children.length-1;e>=0;e--)v(t.children[e]);return t.id?P.adopt(t).id(P.eid(t.nodeName)):P.adopt(t)}function y(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 g(t){var e=(t||"").toString().match(P.regex.reference);if(e)return e[1]}function w(t,e){return Math.sqrt(t*t+e*e)}function b(t,e){var n=Math.sqrt(t*t+e*e),i=t/n,r=e/n;return{theta:180*Math.atan2(e,t)/Math.PI,cos:i,sin:r}}if(!e.createElementNS||!e.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect)return{supported:!1};var P=this.SVG=function(t){if(P.supported)return t=n(t)};P.supported=!0,P.ns="http://www.w3.org/2000/svg",P.xmlns="http://www.w3.org/2000/xmlns/",P.xlink="http://www.w3.org/1999/xlink",P.svgjs="http://svgjs.com/svgjs",P.did=1e3,P.eid=function(t){return"Svgjs"+l(t)+P.did++},P.create=function(t){return e.createElementNS(this.ns,t)},P.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]},P.invent=function(t){var e="function"==typeof t.create?t.create:function(e){this.constructor(e||P.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&P.extend(e,t.extend),t.construct&&P.extend(t.parent||P.Container,t.construct),e},P.adopt=function(e){if(!e)return null;if(e.instance)return e.instance;if(!(e instanceof t.SVGElement))return new P.HtmlNode(e);return"svg"===e.nodeName?e.parentNode instanceof t.SVGElement?new P.Nested(e):new P.Doc(e):"linearGradient"===e.nodeName||"radialGradient"===e.nodeName?new P.Gradient(e):P[l(e.nodeName)]?new(P[l(e.nodeName)])(e):new P.Parent(e)},P.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},P.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})}},P.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"}},P.Color=function(t){var e;this.r=0,this.g=0,this.b=0,t&&("string"==typeof t?P.regex.isRgb.test(t)?(e=P.regex.rgb.exec(t.replace(P.regex.whitespace,"")),this.r=parseInt(e[1]),this.g=parseInt(e[2]),this.b=parseInt(e[3])):P.regex.isHex.test(t)&&(e=P.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))},P.extend(P.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 P.Color(t),this},at:function(t){return this.destination?(t=t<0?0:t>1?1:t,new P.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}}),P.Color.test=function(t){return t+="",P.regex.isHex.test(t)||P.regex.isRgb.test(t)},P.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},P.Color.isColor=function(t){return P.Color.isRgb(t)||P.Color.test(t)},P.Array=function(t,e){t=(t||[]).valueOf(),0===t.length&&e&&(t=e.valueOf()),this.value=this.parse(t)},P.extend(P.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 P.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(P.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}}),P.PointArray=function(t,e){P.Array.call(this,t,e||[[0,0]])},P.PointArray.prototype=new P.Array,P.PointArray.prototype.constructor=P.PointArray,P.extend(P.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 P.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(P.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 M={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]]}},A="mlhvqtcsaz".split(""),N=0,C=A.length;N<C;++N)M[A[N]]=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 M[t](e,n,i)}}(A[N].toUpperCase());P.PathArray=function(t,e){P.Array.call(this,t,e||[["M",0,0]])},P.PathArray.prototype=new P.Array,P.PathArray.prototype.constructor=P.PathArray,P.extend(P.PathArray,{toString:function(){return x(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 P.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 P.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 P.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 P.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(P.regex.numbersWithDots,s).replace(P.regex.pathLetters," $& ").replace(P.regex.hyphen,"$1 -").trim().split(P.regex.delimiter):t.reduce(function(t,e){return[].concat.call(t,e)},[]);var i=[],r=new P.Point,o=new P.Point,a=0,h=t.length;do{P.regex.isPathLetter.test(t[a])?(e=t[a],++a):"M"===e?e="L":"m"===e&&(e="l"),i.push(M[e].call(null,t.slice(a,a+=n[e.toUpperCase()]).map(parseFloat),r,o))}while(h>a);return i},bbox:function(){return P.parser().path.setAttribute("d",this.toString()),P.parser.nodes.path.getBBox()}}),P.Number=P.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(P.regex.numberAndUnit))&&(this.value=parseFloat(e[1]),"%"===e[5]?this.value/=100:"s"===e[5]&&(this.value*=1e3),this.unit=e[5]):t instanceof P.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 P.Number(t),new P.Number(this+t,this.unit||t.unit)},minus:function(t){return t=new P.Number(t),new P.Number(this-t,this.unit||t.unit)},times:function(t){return t=new P.Number(t),new P.Number(this*t,this.unit||t.unit)},divide:function(t){return t=new P.Number(t),new P.Number(this/t,this.unit||t.unit)},to:function(t){var e=new P.Number(this);return"string"==typeof t&&(e.unit=t),e},morph:function(t){return this.destination=new P.Number(t),t.relative&&(this.destination.value+=this.value),this},at:function(t){return this.destination?new P.Number(this.destination).minus(this).times(t).plus(this):this}}}),P.HtmlNode=P.invent({create:function(t){this.node=t},extend:{add:function(t,e){return t=n(t),t instanceof P.Nested&&(t=new P.Doc(t.node),t.setData(JSON.parse(t.node.getAttribute("svgjs:data"))||{})),null===e?this.node.appendChild(t.node):t.node!==this.node.children[e]&&this.node.insertBefore(t.node,this.node.children[e]),this},put:function(t,e){return this.add(t,e),t}}}),P.Element=P.invent({create:function(t){this._event=null,this.dom={},this.node=t,this.node&&(this.type=t.nodeName,this.node.instance=this,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 P.Number(n.width)).height(new P.Number(n.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 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=P.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(P.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 P.get(this.attr(t))},parent:function(e){var n=this;if(!n.node.parentNode)return null;if(n=P.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=P.adopt(n.node.parentNode)}},doc:function(){return this instanceof P.Doc?this:this.parent(P.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 P.Parent))return this.writeDataToDom(),this.node.outerHTML;for(n=e.createElementNS(P.ns,"svg"),n.innerHTML=t,i=n.children.length;i--;)this.node.appendChild(n.firstElementChild);return this},writeDataToDom:function(){return this.is(P.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)}}}),P.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)}},P.morph=function(t){return function(e,n){return new P.MorphObj(e,n).at(t)}},P.Situation=P.invent({create:function(t){this.init=!1,this.reversed=!1,this.reversing=!1,this.duration=new P.Number(t.duration).valueOf(),this.delay=new P.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={}}}),P.FX=P.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 P.Situation({duration:t||1e3,delay:n||0,ease:P.easing[e||"-"]||e});return this.queue(i),this},delay:function(t){var e=new P.Situation({duration:t,delay:0,ease:P.easing["-"]});return this.queue(e)},target:function(t){return t&&t instanceof P.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 P.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 P.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 P.Number&&(n[e]=new P.Number(n[e])),i.animations[t][e]=n[e].morph(i.animations[t][e]);for(t in i.attrs)i.attrs[t]=new P.MorphObj(this.target().attr(t),i.attrs[t]);for(t in i.styles)i.styles[t]=new P.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,P.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,P.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:P.Element,construct:{animate:function(t,e,n){return(this.fx||(this.fx=new P.FX(this))).animate(t,e,n)},delay:function(t){return(this.fx||(this.fx=new P.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}}}),P.MorphObj=P.invent({create:function(t,e){return P.Color.isColor(e)?new P.Color(t).morph(e):P.regex.delimiter.test(t)?new P.Array(t).morph(e):P.regex.numberAndUnit.test(e)?new P.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}}}),P.extend(P.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 P.G)return this.transform({x:t},e),this;var n=new P.Number(t);return n.relative=e,this.add("x",n)},y:function(t,e){if(this.target()instanceof P.G)return this.transform({y:t},e),this;var n=new P.Number(t);return n.relative=e,this.add("y",n)},cx:function(t){return this.add("cx",new P.Number(t))},cy:function(t){return this.add("cy",new P.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 P.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 P.Number(t)).add("height",new P.Number(e))}return this},width:function(t){return this.add("width",new P.Number(t))},height:function(t){return this.add("height",new P.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 P.Number(t)):this},viewbox:function(t,e,n,i){return this.target()instanceof P.Container&&this.add("viewbox",new P.Box(t,e,n,i)),this},update:function(t){if(this.target()instanceof P.Stop){if("number"==typeof t||t instanceof P.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}}),P.Matrix=P.invent({create:function(t){var e,n=p([1,0,0,1,0,0]);for(t=t instanceof P.Element?t.matrixify():"string"==typeof t?p(t.split(P.regex.delimiter).map(parseFloat)):6===arguments.length?p([].slice.call(arguments)):Array.isArray(t)?p(t):"object"==typeof t?t:n,e=k.length-1;e>=0;--e)this[k[e]]=null!=t[k[e]]?t[k[e]]:n[k[e]]},extend:{compose:function(t,e,n){var i=t.translateX||0,r=t.translateY||0,s=t.theta||0,o=t.scaleX||1,a=t.scaleY||1,h=t.shear||0;e=e||0,n=n||0;var u=Math.cos(s*Math.PI/180),l=Math.sin(s*Math.PI/180),c=o*u,f=o*l,d=h*o*u-a*l,p=h*o*l+a*u,m=-o*u*(e+n*h)+a*l*n+i+e,x=-o*l*(e+n*h)-a*u*n+r+n;return new P.Matrix([c,f,d,p,m,x])},decompose:function(t,e,n){var i=t.a,r=t.b,s=t.c,o=t.d,a=t.e,h=t.f,u=b(i,r),l=u.theta,c=u.cos,f=u.sin,d=Math.sign(i*c+r*f),p=d*w(i,r),m=(f*o+c*s)/(c*i+f*r),x=w(m*i-s,o-m*r);return{translateX:a-e+e*c*p+n*(m*c*p-f*x),translateY:h-n+e*f*p+n*(m*f*p+c*x),theta:l,scaleX:p,scaleY:x,shear:m,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f,x:this.e,y:this.f,matrix:new P.Matrix(this)}},form: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.length?t.skew[0]:isFinite(t.skew)?t.skew:isFinite(t.skewX)?t.skewX:0,r=t.skew.length?t.skew[1]:isFinite(t.skew)?t.skew:isFinite(t.skewY)?t.skewY:0,s=t.scale.length?t.scale[0]*e:isFinite(t.scale)?t.scale*e:isFinite(t.scaleX)?t.scaleX*e:e,o=t.scale.length?t.scale[1]*n:isFinite(t.scale)?t.scale*n:isFinite(t.scaleY)?t.scaleY*n:n,a=Math.tan(P.utils.radians(i)),h=Math.tan(P.utils.radians(r)),u=t.shear||0,l=P.utils.radians(t.rotate||0),c=Math.sin(l),f=Math.cos(l),d=t.origin.length?t.origin[0]:t.ox||0,p=t.origin.length?t.origin[1]:t.oy||0,m=t.position.length?t.position[0]:t.px||d,x=t.position.length?t.position[1]:t.py||p,v=t.translate.length?t.translate[0]:t.tx||0,y=t.translate.length?t.translate[1]:t.ty||0,g=f*s+h*c*o,w=f*h*o-c*s,b=f*a*s+c*o+u*(f*s+h*c*o),M=-a*c*s+f*o+u*(-c*s+f*h*o),A=m+v+d*(f*s+h*c*o)+p*(f*a*s+c*o+u*(f*s+h*c*o)),N=x+y+d*(-c*s+f*h*o)+p*(-a*c*s+f*o+u*(-c*s+f*h*o));return new P.Matrix(g,w,b,M,A,N)},clone:function(){return new P.Matrix(this)},morph:function(t){return this.destination=new P.Matrix(t),this},at:function(t){return this.destination?new P.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){return new P.Matrix(this.native().multiply(m(t).native()))},inverse:function(){return new P.Matrix(this.native().inverse())},translate:function(t,e){var n=new P.Matrix(this.native().translate(t||0,e||0));return this.multiply(n)},scale:function(t,e,n,i){1===arguments.length?e=t:3===arguments.length&&(i=n,n=e,e=t);var r=new P.Matrix(t,0,0,e,0,0),s=this.around(n,i,r);return this.multiply(s)},rotate:function(t,e,n){t=P.utils.radians(t);var i=new P.Matrix(Math.cos(t),Math.sin(t),-Math.sin(t),Math.cos(t),0,0),r=this.around(e,n,i);return this.multiply(r)},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,null!=e?e:t)},shear:function(t,e,n){var i=new P.Matrix(1,t,0,1,0,0),r=this.around(e,n,i);return this.multiply(r)},skew:function(t,e,n,i){1===arguments.length?e=t:3===arguments.length&&(i=n,n=e,e=t),t=P.utils.radians(t),e=P.utils.radians(e);var r=new P.Matrix(1,Math.tan(e),Math.tan(t),1,0,0),s=this.around(n,i,r);return this.multiply(s)},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){return this.multiply(new P.Matrix(1,0,0,1,t||0,e||0)).multiply(n).multiply(new P.Matrix(1,0,0,1,-t||0,-e||0))},native:function(){for(var t=P.parser.nodes.svg.node.createSVGMatrix(),e=k.length-1;e>=0;e--)t[k[e]]=this[k[e]];return t},toString:function(){return"matrix("+this.a+","+this.b+","+this.c+","+this.d+","+this.e+","+this.f+")"}},parent:P.Element,construct:{ctm:function(){return new P.Matrix(this.node.getCTM())},screenCTM:function(){if(this instanceof P.Nested){var t=this.rect(1,1),e=t.node.getScreenCTM();return t.remove(),new P.Matrix(e)}return new P.Matrix(this.node.getScreenCTM())}}}),P.Point=P.invent({create:function(t,e){var n,i={x:0,y:0};n=Array.isArray(t)?{x:t[0],y:t[1]}:"object"==typeof t?{x:t.x,y:t.y}:null!=t?{x:t,y:null!=e?e:t}:i,this.x=n.x,this.y=n.y},extend:{clone:function(){return new P.Point(this)},morph:function(t,e){return this.destination=new P.Point(t,e),this},at:function(t){return this.destination?new P.Point({x:this.x+(this.destination.x-this.x)*t,y:this.y+(this.destination.y-this.y)*t}):this},native:function(){var t=P.parser.nodes.svg.node.createSVGPoint()
-;return t.x=this.x,t.y=this.y,t},transform:function(t){return new P.Point(this.native().matrixTransform(t.native()))}}}),P.extend(P.Element,{point:function(t,e){return new P.Point(t,e).transform(this.screenCTM().inverse())}}),P.extend(P.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]=P.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?P.defaults.attrs[t]:P.regex.isNumber.test(e)?parseFloat(e):e;"fill"!==t&&"stroke"!==t||(P.regex.isImage.test(e)&&(e=this.doc().defs().image(e)),e instanceof P.Image&&(e=this.doc().defs().pattern(0,0,function(){this.add(e)}))),"number"==typeof e?e=new P.Number(e):P.Color.isColor(e)?e=new P.Color(e):Array.isArray(e)&&(e=new P.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}}),P.extend(P.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){return(this.attr("transform")||"").split(P.regex.transforms).slice(0,-1).map(function(t){var e=t.trim().split("(");return[e[0],e[1].split(P.regex.delimiter).map(function(t){return parseFloat(t)})]}).reduce(function(t,e){return"matrix"===e[0]?t.multiply(p(e[1])):t[e[0]].apply(t,e[1])},new P.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())}}),P.extend(P.Element,{transform:function(t){if("object"!=typeof t){var e=new P.Matrix(this).decompose();return"string"==typeof t?e[t]:e}if("string"==typeof t.origin){var n=t.origin.toLowerCase().trim(),i=this.bbox(),r=i.x,s=i.y,o=i.width,a=i.height;t.ox=n.includes("left")?r:n.includes("right")?r+o:r+o/2,t.oy=n.includes("top")?s:n.includes("bottom")?s+a:s+a/2,t.origin=null}var h=(new P.Matrix).form(t),u=h.toString();return this.attr("transform",u)},matrix:function(t,e){var n=new P.Matrix(t);if(e){n=new P.Matrix(this).multiply(n)}return this.attr("transform",n)}}),P.extend(P.FX,{transform:function(t,e){}}),P.extend(P.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]||P.regex.isBlank.test(t[i])?"":t[i]}return 2===arguments.length&&(this.node.style[u(t)]=null==e||P.regex.isBlank.test(e)?"":e),this}}),P.Parent=P.invent({create:function(t){this.constructor(t)},inherit:P.Element,extend:{children:function(){return P.utils.map(this.node.children,function(t){return P.adopt(t)})},add:function(t,e){return t=n(t),null==e?this.node.appendChild(t.node):t.node!==this.node.children[e]&&this.node.insertBefore(t.node,this.node.children[e]),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 P.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 P.Element&&t.apply(r[n],[n,r]),e&&r[n]instanceof P.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}}}),P.extend(P.Parent,{flatten:function(t){return this instanceof P.Defs?this:(t=t||(this instanceof P.Doc?this:this.parent(P.Parent)),this.each(function(){return this instanceof P.Defs?this:this instanceof P.Parent?this.flatten(t):this.toParent(t)}),this.node.firstElementChild||this.remove(),this)}}),P.Container=P.invent({create:function(t){this.constructor(t)},inherit:P.Parent}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","touchstart","touchmove","touchleave","touchend","touchcancel"].forEach(function(t){P.Element.prototype[t]=function(e){return P.on(this,t,e),this}}),P.listeners=[],P.handlerMap=[],P.listenerId=0,P.on=function(t,e,n,i,r){e.split(P.regex.delimiter).forEach(function(e){var s=n.bind(i||t),o=t instanceof P.Element?t.node:t,a=(P.handlerMap.indexOf(o)+1||P.handlerMap.push(o))-1,h=e.split(".")[0],u=e.split(".")[1]||"*";P.listeners[a]=P.listeners[a]||{},P.listeners[a][h]=P.listeners[a][h]||{},P.listeners[a][h][u]=P.listeners[a][h][u]||{},n._svgjsListenerId||(n._svgjsListenerId=++P.listenerId),P.listeners[a][h][u][n._svgjsListenerId]=s,o.addEventListener(h,s,r||!1)})},P.off=function(t,e,n){var i=P.handlerMap.indexOf(t),r=e&&e.split(".")[0],s=e&&e.split(".")[1],o="";if(-1!==i)if(n){if("function"==typeof n&&(n=n._svgjsListenerId),!n)return;P.listeners[i][r]&&P.listeners[i][r][s||"*"]&&(t.removeEventListener(r,P.listeners[i][r][s||"*"][n],!1),delete P.listeners[i][r][s||"*"][n])}else if(s&&r){if(P.listeners[i][r]&&P.listeners[i][r][s]){for(n in P.listeners[i][r][s])P.off(t,[r,s].join("."),n);delete P.listeners[i][r][s]}}else if(s)for(e in P.listeners[i])for(o in P.listeners[i][e])s===o&&P.off(t,[e,s].join("."));else if(r){if(P.listeners[i][r]){for(o in P.listeners[i][r])P.off(t,[r,o].join("."));delete P.listeners[i][r]}}else{for(e in P.listeners[i])P.off(t,e);delete P.listeners[i],delete P.handlerMap[i]}},P.extend(P.Element,{on:function(t,e,n,i){return P.on(this,t,e,n,i),this},off:function(t,e){return P.off(this.node,t,e),this},fire:function(e,n){return e instanceof t.Event?this.node.dispatchEvent(e):this.node.dispatchEvent(e=new t.CustomEvent(e,{detail:n,cancelable:!0})),this._event=e,this},event:function(){return this._event}}),P.Defs=P.invent({create:"defs",inherit:P.Container}),P.G=P.invent({create:"g",inherit:P.Container,extend:{x:function(t){return null==t?this.transform("x"):this.transform({x:t-this.x()},!0)},y:function(t){return null==t?this.transform("y"):this.transform({y:t-this.y()},!0)},cx:function(t){return null==t?this.gbox().cx:this.x(t-this.gbox().width/2)},cy:function(t){return null==t?this.gbox().cy:this.y(t-this.gbox().height/2)},gbox:function(){var t=this.bbox(),e=this.transform();return t.x+=e.x,t.x2+=e.x,t.cx+=e.x,t.y+=e.y,t.y2+=e.y,t.cy+=e.y,t}},construct:{group:function(){return this.put(new P.G)}}}),P.extend(P.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 P.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 P.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}}),P.Mask=P.invent({create:"mask",inherit:P.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unmask()}),P.Element.prototype.remove.call(this)},targets:function(){return P.select('svg [mask*="'+this.id()+'"]')}},construct:{mask:function(){return this.defs().put(new P.Mask)}}}),P.extend(P.Element,{maskWith:function(t){var e=t instanceof P.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")}}),P.ClipPath=P.invent({create:"clipPath",inherit:P.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unclip()}),P.Element.prototype.remove.call(this)},targets:function(){return P.select('svg [clip-path*="'+this.id()+'"]')}},construct:{clip:function(){return this.defs().put(new P.ClipPath)}}}),P.extend(P.Element,{clipWith:function(t){var e=t instanceof P.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")}}),P.Gradient=P.invent({create:function(t){this.constructor("object"==typeof t?t:P.create(t+"Gradient"))},inherit:P.Container,extend:{stop:function(t,e,n){return this.put(new P.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"),P.Container.prototype.attr.call(this,t,e,n)}},construct:{gradient:function(t,e){return this.defs().gradient(t,e)}}}),P.extend([P.Gradient,P.FX],{from:function(t,e){return"radialGradient"===(this._target||this).type?this.attr({fx:new P.Number(t),fy:new P.Number(e)}):this.attr({x1:new P.Number(t),y1:new P.Number(e)})},to:function(t,e){return"radialGradient"===(this._target||this).type?this.attr({cx:new P.Number(t),cy:new P.Number(e)}):this.attr({x2:new P.Number(t),y2:new P.Number(e)})}}),P.extend(P.Defs,{gradient:function(t,e){return this.put(new P.Gradient(t)).update(e)}}),P.Stop=P.invent({create:"stop",inherit:P.Element,extend:{update:function(t){return("number"==typeof t||t instanceof P.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 P.Number(t.offset)),this}}}),P.Pattern=P.invent({create:"pattern",inherit:P.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"),P.Container.prototype.attr.call(this,t,e,n)}},construct:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}}}),P.extend(P.Defs,{pattern:function(t,e,n){return this.put(new P.Pattern).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}),P.Doc=P.invent({create:function(t){this.constructor(t||P.create("svg")),this.namespace().defs()},inherit:P.Container,extend:{namespace:function(){return this.attr({xmlns:P.ns,version:"1.1"}).attr("xmlns:xlink",P.xlink,P.xmlns).attr("xmlns:svgjs",P.svgjs,P.xmlns)},defs:function(){return P.adopt(this.node.getElementsByTagName("defs")[0])||this.put(new P.Defs)},parent:function(){return"#document"===this.node.parentNode.nodeName?null:this.node.parentNode},remove:function(){return this.parent()&&this.parent().removeChild(this.node),this},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this},toNested:function(){var t=P.create("svg");return this.node.instance=null,t.appendChild(this.node),P.adopt(this.node)}}}),P.Shape=P.invent({create:function(t){this.constructor(t)},inherit:P.Element}),P.Bare=P.invent({create:function(t,e){if(this.constructor(P.create(t)),e)for(var n in e.prototype)"function"==typeof e.prototype[n]&&(this[n]=e.prototype[n])},inherit:P.Element,extend:{words:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(e.createTextNode(t)),this}}}),P.extend(P.Parent,{element:function(t,e){return this.put(new P.Bare(t,e))}}),P.Symbol=P.invent({create:"symbol",inherit:P.Container,construct:{symbol:function(){return this.put(new P.Symbol)}}}),P.Use=P.invent({create:"use",inherit:P.Shape,extend:{element:function(t,e){return this.attr("href",(e||"")+"#"+t,P.xlink)}},construct:{use:function(t,e){return this.put(new P.Use).element(t,e)}}}),P.Rect=P.invent({create:"rect",inherit:P.Shape,construct:{rect:function(t,e){return this.put(new P.Rect).size(t,e)}}}),P.Circle=P.invent({create:"circle",inherit:P.Shape,construct:{circle:function(t){return this.put(new P.Circle).rx(new P.Number(t).divide(2)).move(0,0)}}}),P.extend([P.Circle,P.FX],{rx:function(t){return this.attr("r",t)},ry:function(t){return this.rx(t)}}),P.Ellipse=P.invent({create:"ellipse",inherit:P.Shape,construct:{ellipse:function(t,e){return this.put(new P.Ellipse).size(t,e).move(0,0)}}}),P.extend([P.Ellipse,P.Rect,P.FX],{rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)}}),P.extend([P.Circle,P.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 P.Number(t).divide(2))},height:function(t){return null==t?2*this.ry():this.ry(new P.Number(t).divide(2))},size:function(t,e){var n=d(this,t,e);return this.rx(new P.Number(n.width).divide(2)).ry(new P.Number(n.height).divide(2))}}),P.Line=P.invent({create:"line",inherit:P.Shape,extend:{array:function(){return new P.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 P.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 P.Line.prototype.plot.apply(this.put(new P.Line),null!=t?[t,e,n,i]:[0,0,0,0])}}}),P.Polyline=P.invent({create:"polyline",inherit:P.Shape,construct:{polyline:function(t){return this.put(new P.Polyline).plot(t||new P.PointArray)}}}),P.Polygon=P.invent({create:"polygon",inherit:P.Shape,construct:{polygon:function(t){return this.put(new P.Polygon).plot(t||new P.PointArray)}}}),P.extend([P.Polyline,P.Polygon],{array:function(){return this._array||(this._array=new P.PointArray(this.attr("points")))},plot:function(t){return null==t?this.array():this.clear().attr("points","string"==typeof t?t:this._array=new P.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))}}),P.extend([P.Line,P.Polyline,P.Polygon],{MorphArray:P.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)}}),P.Path=P.invent({create:"path",inherit:P.Shape,extend:{MorphArray:P.PathArray,array:function(){return this._array||(this._array=new P.PathArray(this.attr("d")))},plot:function(t){return null==t?this.array():this.clear().attr("d","string"==typeof t?t:this._array=new P.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 P.Path).plot(t||new P.PathArray)}}}),P.Image=P.invent({create:"image",inherit:P.Shape,extend:{load:function(e,n){if(!e)return this;var i=new t.Image;return P.on(i,"load",function(t){var r=this.parent(P.Pattern);0===this.width()&&0===this.height()&&this.size(i.width,i.height),r instanceof P.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),P.on(i,"load error",function(){P.off(i)}),this.attr("href",i.src=e,P.xlink)}},construct:{image:function(t,e){return this.put(new P.Image).size(0,0).load(t,e)}}}),P.Text=P.invent({create:function(t){this.constructor(t||P.create("text")),this.dom.leading=new P.Number(1.3),this._rebuild=!0,this._build=!1,this.attr("font-family",P.defaults.attrs["font-family"])},inherit:P.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===P.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()},size:function(t){return this.attr("font-size",t).rebuild()},leading:function(t){return null==t?this.dom.leading:(this.dom.leading=new P.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 P.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 P.Number(t.leading||1.3),this}},construct:{text:function(t){return this.put(new P.Text).text(t)},plain:function(t){return this.put(new P.Text).plain(t)}}}),P.Tspan=P.invent({create:"tspan",inherit:P.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(P.Text);return this.dom.newLined=!0,this.dy(t.dom.leading*t.attr("font-size")).attr("x",t.x())}}}),P.extend([P.Text,P.Tspan],{plain:function(t){return!1===this._build&&this.clear(),this.node.appendChild(e.createTextNode(t)),this},tspan:function(t){var e=new P.Tspan;return this._build||this.clear(),this.node.appendChild(e.node),e.text(t)},length:function(){return this.node.getComputedTextLength()}}),P.TextPath=P.invent({create:"textPath",inherit:P.Text,parent:P.Parent,extend:{MorphArray:P.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)}}}),P.extend([P.Text],{path:function(t){var e=new P.TextPath;return t instanceof P.Path||(t=this.doc().defs().path(t)),e.attr("href","#"+t,P.xlink),this.put(e)},textPath:function(){return this.select("textPath")}}),P.extend([P.Path],{text:function(t){if(t instanceof P.Text){var e=t.text();return t.clear().path(this).text(e)}return this.parent().put(new P.Text).path(this).text(t)}}),P.Nested=P.invent({create:"svg",inherit:P.Container,construct:{nested:function(){return this.put(new P.Nested)}}}),P.A=P.invent({create:"a",inherit:P.Container,extend:{to:function(t){return this.attr("href",t,P.xlink)},target:function(t){return this.attr("target",t)}},construct:{link:function(t){return this.put(new P.A).to(t)}}}),P.extend(P.Element,{linkTo:function(t){var e=new P.A;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}),P.Marker=P.invent({create:"marker",inherit:P.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)}}}),P.extend(P.Defs,{marker:function(t,e,n){return this.put(new P.Marker).size(t,e).ref(t/2,e/2).viewbox(0,0,t,e).attr("orient","auto").update(n)}}),P.extend([P.Line,P.Polyline,P.Polygon,P.Path],{marker:function(t,e,n,i){var r=["marker"];return"all"!==t&&r.push(t),r=r.join("-"),t=arguments[1]instanceof P.Marker?arguments[1]:this.doc().marker(e,n,i),this.attr(r,t)}});var S={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||P.Color.isRgb(n)||n&&"function"==typeof n.fill)this.attr(t,n);else for(e=S[t].length-1;e>=0;e--)null!=n[S[t][e]]&&this.attr(S.prefix(t,S[t][e]),n[S[t][e]]);return this},P.extend([P.Element,P.FX],n)}),P.extend([P.Element,P.FX],{rotate:function(t,e,n){var i=(new P.Matrix).rotate(t,e,n);return this.matrix(i,!0)},skew:function(t,e,n,i){var r=1===arguments.length||3===arguments.length?(new P.Matrix).skew(t,t,n,i):(new P.Matrix).skew(t,e,n,i);return this.matrix(r,!0)},scale:function(t,e,n,i){return 1===arguments.length||3===arguments.length?this.transform({scale:t,cx:e,cy:n}):this.transform({scaleX:t,scaleY:e,cx:n,cy:i})},translate:function(t,e){return this.transform({x:t,y:e})},flip:function(t,e){return e="number"==typeof t?t:e,this.transform({flip:t||"both",offset:e})},opacity:function(t){return this.attr("opacity",t)},dx:function(t){return this.x(new P.Number(t).plus(this instanceof P.FX?0:this.x()),!0)},dy:function(t){return this.y(new P.Number(t).plus(this instanceof P.FX?0:this.y()),!0)},dmove:function(t,e){return this.dx(t).dy(e)}}),P.extend([P.Rect,P.Ellipse,P.Circle,P.Gradient,P.FX],{radius:function(t,e){var n=(this._target||this).type;return"radialGradient"===n||"radialGradient"===n?this.attr("r",new P.Number(t)):this.rx(t).ry(null==e?t:e)}}),P.extend(P.Path,{length:function(){return this.node.getTotalLength()},pointAt:function(t){return new P.Point(this.node.getPointAtLength(t))}}),P.extend([P.Parent,P.Text,P.Tspan,P.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)}}),P.extend(P.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}}),P.extend(P.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={})}}),P.get=function(t){var n=e.getElementById(g(t)||t);return P.adopt(n)},P.select=function(t,n){return P.utils.map((n||e).querySelectorAll(t),function(t){return P.adopt(t)})},P.$$=function(t,n){return P.utils.map((n||e).querySelectorAll(t),function(t){return P.adopt(t)})},P.$=function(t,n){return P.adopt((n||e).querySelector(t))},P.extend(P.Parent,{select:function(t){return P.select(t,this.node)}});var k="abcdef".split("");return P.Box=P.invent({create:function(t){var e=[0,0,0,0];t="string"==typeof t?t.split(P.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],y(this)},extend:{merge:function(t){var e=Math.min(this.x,t.x),n=Math.min(this.y,t.y);return new P.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 P.Point(this.x,this.y),new P.Point(this.x2,this.y),new P.Point(this.x,this.y2),new P.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 P.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 P.Box(t,e,n,i),this},at:function(t){return this.destination?new P.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:P.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(P.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 P.Box(t)},rbox:function(t){try{var e=new P.Box(this.node.getBoundingClientRect());return t?e.transform(t.screenCTM().inverse()):e.addOffset()}catch(t){return new P.Box}}}}),P.extend([P.Doc,P.Nested,P.Symbol,P.Image,P.Pattern,P.Marker,P.ForeignObject,P.View],{viewbox:function(t,e,n,i){return null==t?new P.Box(this.attr("viewBox")):this.attr("viewBox",new P.Box(t,e,n,i))}}),P.parser=function(){var t;return P.parser.nodes.svg.node.parentNode||(t=e.body||e.documentElement,P.parser.nodes.svg.addTo(t)),P.parser.nodes},P.parser.nodes={svg:(new P.Nested).size(2,0).css({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"})},P.parser.nodes.path=P.parser.nodes.svg.path().node,P}); \ 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 n(t,n){if(t instanceof A.Element)return t;if("object"==typeof t)return A.adopt(t);if(null==t)return new A.Doc;if("string"==typeof t&&"<"!==t.charAt(0))return A.adopt(e.querySelector(t));var i=A.create("svg");return i.innerHTML=t,t=A.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(A.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){return t instanceof A.Matrix||(t=new A.Matrix(t)),t}function x(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 v(t){for(var e=t.children.length-1;e>=0;e--)v(t.children[e]);return t.id?A.adopt(t).id(A.eid(t.nodeName)):A.adopt(t)}function g(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(A.regex.reference);if(e)return e[1]}function w(t,e){return Math.sqrt(t*t+e*e)}function b(t,e){var n=Math.atan2(e,t);return{theta:180*n/Math.PI,cos:Math.cos(n),sin:Math.sin(n)}}function P(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 A=this.SVG=function(t){if(A.supported)return t=n(t)};A.supported=!0,A.ns="http://www.w3.org/2000/svg",A.xmlns="http://www.w3.org/2000/xmlns/",A.xlink="http://www.w3.org/1999/xlink",A.svgjs="http://svgjs.com/svgjs",A.did=1e3,A.eid=function(t){return"Svgjs"+l(t)+A.did++},A.create=function(t){return e.createElementNS(this.ns,t)},A.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]},A.invent=function(t){var e="function"==typeof t.create?t.create:function(e){this.constructor(e||A.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&A.extend(e,t.extend),t.construct&&A.extend(t.parent||A.Container,t.construct),e},A.adopt=function(e){if(!e)return null;if(e.instance)return e.instance;if(!(e instanceof t.SVGElement))return new A.HtmlNode(e);return"svg"===e.nodeName?e.parentNode instanceof t.SVGElement?new A.Nested(e):new A.Doc(e):"linearGradient"===e.nodeName||"radialGradient"===e.nodeName?new A.Gradient(e):A[l(e.nodeName)]?new(A[l(e.nodeName)])(e):new A.Parent(e)},A.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},A.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})}},A.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"}},A.Color=function(t){var e;this.r=0,this.g=0,this.b=0,t&&("string"==typeof t?A.regex.isRgb.test(t)?(e=A.regex.rgb.exec(t.replace(A.regex.whitespace,"")),this.r=parseInt(e[1]),this.g=parseInt(e[2]),this.b=parseInt(e[3])):A.regex.isHex.test(t)&&(e=A.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))},A.extend(A.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 A.Color(t),this},at:function(t){return this.destination?(t=t<0?0:t>1?1:t,new A.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}}),A.Color.test=function(t){return t+="",A.regex.isHex.test(t)||A.regex.isRgb.test(t)},A.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},A.Color.isColor=function(t){return A.Color.isRgb(t)||A.Color.test(t)},A.Array=function(t,e){t=(t||[]).valueOf(),0===t.length&&e&&(t=e.valueOf()),this.value=this.parse(t)},A.extend(A.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 A.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(A.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}}),A.PointArray=function(t,e){A.Array.call(this,t,e||[[0,0]])},A.PointArray.prototype=new A.Array,A.PointArray.prototype.constructor=A.PointArray,A.extend(A.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 A.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(A.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 N={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]]}},C="mlhvqtcsaz".split(""),M=0,S=C.length;M<S;++M)N[C[M]]=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 N[t](e,n,i)}}(C[M].toUpperCase());A.PathArray=function(t,e){A.Array.call(this,t,e||[["M",0,0]])},A.PathArray.prototype=new A.Array,A.PathArray.prototype.constructor=A.PathArray,A.extend(A.PathArray,{toString:function(){return x(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 A.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 A.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 A.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 A.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(A.regex.numbersWithDots,s).replace(A.regex.pathLetters," $& ").replace(A.regex.hyphen,"$1 -").trim().split(A.regex.delimiter):t.reduce(function(t,e){return[].concat.call(t,e)},[]);var i=[],r=new A.Point,o=new A.Point,a=0,h=t.length;do{A.regex.isPathLetter.test(t[a])?(e=t[a],++a):"M"===e?e="L":"m"===e&&(e="l"),i.push(N[e].call(null,t.slice(a,a+=n[e.toUpperCase()]).map(parseFloat),r,o))}while(h>a);return i},bbox:function(){return A.parser().path.setAttribute("d",this.toString()),A.parser.nodes.path.getBBox()}}),A.Number=A.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(A.regex.numberAndUnit))&&(this.value=parseFloat(e[1]),"%"===e[5]?this.value/=100:"s"===e[5]&&(this.value*=1e3),this.unit=e[5]):t instanceof A.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 A.Number(t),new A.Number(this+t,this.unit||t.unit)},minus:function(t){return t=new A.Number(t),new A.Number(this-t,this.unit||t.unit)},times:function(t){return t=new A.Number(t),new A.Number(this*t,this.unit||t.unit)},divide:function(t){return t=new A.Number(t),new A.Number(this/t,this.unit||t.unit)},to:function(t){var e=new A.Number(this);return"string"==typeof t&&(e.unit=t),e},morph:function(t){return this.destination=new A.Number(t),t.relative&&(this.destination.value+=this.value),this},at:function(t){return this.destination?new A.Number(this.destination).minus(this).times(t).plus(this):this}}}),A.HtmlNode=A.invent({create:function(t){this.node=t},extend:{add:function(t,e){return t=n(t),t instanceof A.Nested&&(t=new A.Doc(t.node),t.setData(JSON.parse(t.node.getAttribute("svgjs:data"))||{})),null===e?this.node.appendChild(t.node):t.node!==this.node.children[e]&&this.node.insertBefore(t.node,this.node.children[e]),this},put:function(t,e){return this.add(t,e),t}}}),A.Element=A.invent({create:function(t){this._event=null,this.dom={},this.node=t,this.node&&(this.type=t.nodeName,this.node.instance=this,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 A.Number(n.width)).height(new A.Number(n.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 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=A.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(A.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 A.get(this.attr(t))},parent:function(e){var n=this;if(!n.node.parentNode)return null;if(n=A.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=A.adopt(n.node.parentNode)}},doc:function(){return this instanceof A.Doc?this:this.parent(A.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 A.Parent))return this.writeDataToDom(),this.node.outerHTML;for(n=e.createElementNS(A.ns,"svg"),n.innerHTML=t,i=n.children.length;i--;)this.node.appendChild(n.firstElementChild);return this},writeDataToDom:function(){return this.is(A.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)}}}),A.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)}},A.morph=function(t){return function(e,n){return new A.MorphObj(e,n).at(t)}},A.Situation=A.invent({create:function(t){this.init=!1,this.reversed=!1,this.reversing=!1,this.duration=new A.Number(t.duration).valueOf(),this.delay=new A.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={}}}),A.FX=A.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 A.Situation({duration:t||1e3,delay:n||0,ease:A.easing[e||"-"]||e});return this.queue(i),this},delay:function(t){var e=new A.Situation({duration:t,delay:0,ease:A.easing["-"]});return this.queue(e)},target:function(t){return t&&t instanceof A.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 A.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 A.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 A.Number&&(n[e]=new A.Number(n[e])),i.animations[t][e]=n[e].morph(i.animations[t][e]);for(t in i.attrs)i.attrs[t]=new A.MorphObj(this.target().attr(t),i.attrs[t]);for(t in i.styles)i.styles[t]=new A.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,A.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,A.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:A.Element,construct:{animate:function(t,e,n){return(this.fx||(this.fx=new A.FX(this))).animate(t,e,n)},delay:function(t){return(this.fx||(this.fx=new A.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}}}),A.MorphObj=A.invent({create:function(t,e){return A.Color.isColor(e)?new A.Color(t).morph(e):A.regex.delimiter.test(t)?new A.Array(t).morph(e):A.regex.numberAndUnit.test(e)?new A.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}}}),A.extend(A.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 A.G)return this.transform({x:t},e),this;var n=new A.Number(t);return n.relative=e,this.add("x",n)},y:function(t,e){if(this.target()instanceof A.G)return this.transform({y:t},e),this;var n=new A.Number(t);return n.relative=e,this.add("y",n)},cx:function(t){return this.add("cx",new A.Number(t))},cy:function(t){return this.add("cy",new A.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 A.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 A.Number(t)).add("height",new A.Number(e))}return this},width:function(t){return this.add("width",new A.Number(t))},height:function(t){return this.add("height",new A.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 A.Number(t)):this},viewbox:function(t,e,n,i){return this.target()instanceof A.Container&&this.add("viewbox",new A.Box(t,e,n,i)),this},update:function(t){if(this.target()instanceof A.Stop){if("number"==typeof t||t instanceof A.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}}),A.compose=function(t,e,n){var i=t.translateX||0,r=t.translateY||0,s=t.theta||0,o=t.scaleX||1,a=t.scaleY||1,h=t.shear||0;e=e||0,n=n||0;var u=Math.cos(s*Math.PI/180),l=Math.sin(s*Math.PI/180),c=o*u,f=o*l,d=h*o*u-a*l,p=h*o*l+a*u,m=-o*u*(e+n*h)+a*l*n+i+e,x=-o*l*(e+n*h)-a*u*n+r+n;return new A.Matrix([c,f,d,p,m,x])},A.Matrix=A.invent({create:function(t){var e,n=p([1,0,0,1,0,0]);for(t=t instanceof A.Element?t.matrixify():"string"==typeof t?p(t.split(A.regex.delimiter).map(parseFloat)):6===arguments.length?p([].slice.call(arguments)):Array.isArray(t)?p(t):"object"==typeof t?t:n,e=E.length-1;e>=0;--e)this[E[e]]=null!=t[E[e]]?t[E[e]]:n[E[e]]},extend:{decompose:function(t,e){t=t||0,e=e||0;var n=this.a,i=this.b,r=this.c,s=this.d,o=this.e,a=this.f,h=b(n,i),u=h.theta,l=h.cos,c=h.sin,f=Math.sign(n*l+i*c),d=f*w(n,i),p=(c*s+l*r)/(l*n+c*i),m=w(p*n-r,s-p*i);return{translateX:o-t+t*l*d+e*(p*l*d-c*m),translateY:a-e+t*c*d+e*(p*c*d+l*m),rotate:u,scaleX:d,scaleY:m,shear:p,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f,x:this.e,y:this.f,matrix:new A.Matrix(this)}},affine: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=t.origin&&t.origin.length?t.origin[0]:t.ox||0,l=t.origin&&t.origin.length?t.origin[1]:t.oy||0,c=t.position&&t.position.length?t.position[0]:t.px,f=t.position&&t.position.length?t.position[1]:t.py,d=t.translate&&t.translate.length?t.translate[0]:t.tx||0,p=t.translate&&t.translate.length?t.translate[1]:t.ty||0,m=(new A.Matrix).translate(-u,-l).scale(s,o).skew(i,r).shear(a).rotate(h).translate(u,l).translate(d,p).lmultiply(new A.Matrix(this));if(isFinite(c)&&isFinite(f)){var x=new A.Point(u-d,l-p).transform(m),v=c-x.x,g=f-x.y;m=m.translate(v,g)}return m},clone:function(){return new A.Matrix(this)},morph:function(t){return this.destination=new A.Matrix(t),this},at:function(t){return this.destination?new A.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=m(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 A.Matrix(i,r,s,o,a,h)},lmultiply:function(t){return m(t).multiply(this)},inverse:function(){return new A.Matrix(this.native().inverse())},translate:function(t,e){var n=new A.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 A.Matrix(t,0,0,e,0,0);return this.around(n,i,r)},rotate:function(t,e,n){t=A.utils.radians(t);var i=new A.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 A.Matrix(1,t,0,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=A.utils.radians(t),e=A.utils.radians(e);var r=new A.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=A.parser.nodes.svg.node.createSVGMatrix(),e=E.length-1;e>=0;e--)t[E[e]]=this[E[e]];return t},equals:function(t){var e=m(t);return P(this.a,e.a)&&P(this.b,e.b)&&P(this.c,e.c)&&P(this.d,e.d)&&P(this.e,e.e)&&P(this.f,e.f)},toString:function(){return"matrix("+this.a+","+this.b+","+this.c+","+this.d+","+this.e+","+this.f+")"}},parent:A.Element,construct:{ctm:function(){return new A.Matrix(this.node.getCTM())},screenCTM:function(){if(this instanceof A.Nested){var t=this.rect(1,1),e=t.node.getScreenCTM();return t.remove(),new A.Matrix(e)}return new A.Matrix(this.node.getScreenCTM())}}}),A.Point=A.invent({create:function(t,e){var n,i={x:0,y:0};n=Array.isArray(t)?{x:t[0],y:t[1]}:"object"==typeof t?{x:t.x,y:t.y}:null!=t?{x:t,y:null!=e?e:t}:i,this.x=n.x,this.y=n.y},extend:{clone:function(){return new A.Point(this)},morph:function(t,e){
+return this.destination=new A.Point(t,e),this},at:function(t){return this.destination?new A.Point({x:this.x+(this.destination.x-this.x)*t,y:this.y+(this.destination.y-this.y)*t}):this},native:function(){var t=A.parser.nodes.svg.node.createSVGPoint();return t.x=this.x,t.y=this.y,t},transform:function(t){return new A.Point(this.native().matrixTransform(t.native()))}}}),A.extend(A.Element,{point:function(t,e){return new A.Point(t,e).transform(this.screenCTM().inverse())}}),A.extend(A.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]=A.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?A.defaults.attrs[t]:A.regex.isNumber.test(e)?parseFloat(e):e;"fill"!==t&&"stroke"!==t||(A.regex.isImage.test(e)&&(e=this.doc().defs().image(e)),e instanceof A.Image&&(e=this.doc().defs().pattern(0,0,function(){this.add(e)}))),"number"==typeof e?e=new A.Number(e):A.Color.isColor(e)?e=new A.Color(e):Array.isArray(e)&&(e=new A.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}}),A.extend(A.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){return(this.attr("transform")||"").split(A.regex.transforms).slice(0,-1).map(function(t){var e=t.trim().split("(");return[e[0],e[1].split(A.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 A.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())}}),A.extend(A.Element,{transform:function(t,e){var n=this.bbox();if(null==t)return new A.Matrix(this);if(null!=t.a){var i=new A.Matrix(t);if(null!=e){var r=new A.Matrix(this);i=i.multiply(r)}return this.attr("transform",i)}if("string"==typeof t.origin||null==t.origin&&null==t.ox&&null==t.oy){var s="string"==typeof t.origin?t.origin.toLowerCase().trim():"center",o=n.height,a=n.width,h=n.x,u=n.y;t.ox=s.includes("left")?h:s.includes("right")?h+a:h+a/2,t.oy=s.includes("top")?u:s.includes("bottom")?u+o:u+o/2,t.origin=null}var l=new A.Matrix(!0===e?this:e).affine(t),c=l.toString();return this.attr("transform",c)}}),A.extend(A.FX,{transform:function(t,e){}}),A.extend(A.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]||A.regex.isBlank.test(t[i])?"":t[i]}return 2===arguments.length&&(this.node.style[u(t)]=null==e||A.regex.isBlank.test(e)?"":e),this}}),A.Parent=A.invent({create:function(t){this.constructor(t)},inherit:A.Element,extend:{children:function(){return A.utils.map(this.node.children,function(t){return A.adopt(t)})},add:function(t,e){return t=n(t),null==e?this.node.appendChild(t.node):t.node!==this.node.children[e]&&this.node.insertBefore(t.node,this.node.children[e]),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 A.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 A.Element&&t.apply(r[n],[n,r]),e&&r[n]instanceof A.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}}}),A.extend(A.Parent,{flatten:function(t){return this instanceof A.Defs?this:(t=t||(this instanceof A.Doc?this:this.parent(A.Parent)),this.each(function(){return this instanceof A.Defs?this:this instanceof A.Parent?this.flatten(t):this.toParent(t)}),this.node.firstElementChild||this.remove(),this)}}),A.Container=A.invent({create:function(t){this.constructor(t)},inherit:A.Parent}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","touchstart","touchmove","touchleave","touchend","touchcancel"].forEach(function(t){A.Element.prototype[t]=function(e){return A.on(this,t,e),this}}),A.listeners=[],A.handlerMap=[],A.listenerId=0,A.on=function(t,e,n,i,r){e.split(A.regex.delimiter).forEach(function(e){var s=n.bind(i||t),o=t instanceof A.Element?t.node:t,a=(A.handlerMap.indexOf(o)+1||A.handlerMap.push(o))-1,h=e.split(".")[0],u=e.split(".")[1]||"*";A.listeners[a]=A.listeners[a]||{},A.listeners[a][h]=A.listeners[a][h]||{},A.listeners[a][h][u]=A.listeners[a][h][u]||{},n._svgjsListenerId||(n._svgjsListenerId=++A.listenerId),A.listeners[a][h][u][n._svgjsListenerId]=s,o.addEventListener(h,s,r||!1)})},A.off=function(t,e,n){var i=A.handlerMap.indexOf(t),r=e&&e.split(".")[0],s=e&&e.split(".")[1],o="";if(-1!==i)if(n){if("function"==typeof n&&(n=n._svgjsListenerId),!n)return;A.listeners[i][r]&&A.listeners[i][r][s||"*"]&&(t.removeEventListener(r,A.listeners[i][r][s||"*"][n],!1),delete A.listeners[i][r][s||"*"][n])}else if(s&&r){if(A.listeners[i][r]&&A.listeners[i][r][s]){for(n in A.listeners[i][r][s])A.off(t,[r,s].join("."),n);delete A.listeners[i][r][s]}}else if(s)for(e in A.listeners[i])for(o in A.listeners[i][e])s===o&&A.off(t,[e,s].join("."));else if(r){if(A.listeners[i][r]){for(o in A.listeners[i][r])A.off(t,[r,o].join("."));delete A.listeners[i][r]}}else{for(e in A.listeners[i])A.off(t,e);delete A.listeners[i],delete A.handlerMap[i]}},A.extend(A.Element,{on:function(t,e,n,i){return A.on(this,t,e,n,i),this},off:function(t,e){return A.off(this.node,t,e),this},fire:function(e,n){return e instanceof t.Event?this.node.dispatchEvent(e):this.node.dispatchEvent(e=new t.CustomEvent(e,{detail:n,cancelable:!0})),this._event=e,this},event:function(){return this._event}}),A.Defs=A.invent({create:"defs",inherit:A.Container}),A.G=A.invent({create:"g",inherit:A.Container,extend:{x:function(t){return null==t?this.transform("x"):this.transform({x:t-this.x()},!0)},y:function(t){return null==t?this.transform("y"):this.transform({y:t-this.y()},!0)},cx:function(t){return null==t?this.gbox().cx:this.x(t-this.gbox().width/2)},cy:function(t){return null==t?this.gbox().cy:this.y(t-this.gbox().height/2)},gbox:function(){var t=this.bbox(),e=this.transform();return t.x+=e.x,t.x2+=e.x,t.cx+=e.x,t.y+=e.y,t.y2+=e.y,t.cy+=e.y,t}},construct:{group:function(){return this.put(new A.G)}}}),A.extend(A.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 A.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 A.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}}),A.Mask=A.invent({create:"mask",inherit:A.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unmask()}),A.Element.prototype.remove.call(this)},targets:function(){return A.select('svg [mask*="'+this.id()+'"]')}},construct:{mask:function(){return this.defs().put(new A.Mask)}}}),A.extend(A.Element,{maskWith:function(t){var e=t instanceof A.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")}}),A.ClipPath=A.invent({create:"clipPath",inherit:A.Container,extend:{remove:function(){return this.targets().forEach(function(t){t.unclip()}),A.Element.prototype.remove.call(this)},targets:function(){return A.select('svg [clip-path*="'+this.id()+'"]')}},construct:{clip:function(){return this.defs().put(new A.ClipPath)}}}),A.extend(A.Element,{clipWith:function(t){var e=t instanceof A.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")}}),A.Gradient=A.invent({create:function(t){this.constructor("object"==typeof t?t:A.create(t+"Gradient"))},inherit:A.Container,extend:{stop:function(t,e,n){return this.put(new A.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"),A.Container.prototype.attr.call(this,t,e,n)}},construct:{gradient:function(t,e){return this.defs().gradient(t,e)}}}),A.extend([A.Gradient,A.FX],{from:function(t,e){return"radialGradient"===(this._target||this).type?this.attr({fx:new A.Number(t),fy:new A.Number(e)}):this.attr({x1:new A.Number(t),y1:new A.Number(e)})},to:function(t,e){return"radialGradient"===(this._target||this).type?this.attr({cx:new A.Number(t),cy:new A.Number(e)}):this.attr({x2:new A.Number(t),y2:new A.Number(e)})}}),A.extend(A.Defs,{gradient:function(t,e){return this.put(new A.Gradient(t)).update(e)}}),A.Stop=A.invent({create:"stop",inherit:A.Element,extend:{update:function(t){return("number"==typeof t||t instanceof A.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 A.Number(t.offset)),this}}}),A.Pattern=A.invent({create:"pattern",inherit:A.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"),A.Container.prototype.attr.call(this,t,e,n)}},construct:{pattern:function(t,e,n){return this.defs().pattern(t,e,n)}}}),A.extend(A.Defs,{pattern:function(t,e,n){return this.put(new A.Pattern).update(n).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}),A.Doc=A.invent({create:function(t){this.constructor(t||A.create("svg")),this.namespace().defs()},inherit:A.Container,extend:{namespace:function(){return this.attr({xmlns:A.ns,version:"1.1"}).attr("xmlns:xlink",A.xlink,A.xmlns).attr("xmlns:svgjs",A.svgjs,A.xmlns)},defs:function(){return A.adopt(this.node.getElementsByTagName("defs")[0])||this.put(new A.Defs)},parent:function(){return"#document"===this.node.parentNode.nodeName?null:this.node.parentNode},remove:function(){return this.parent()&&this.parent().removeChild(this.node),this},clear:function(){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this},toNested:function(){var t=A.create("svg");return this.node.instance=null,t.appendChild(this.node),A.adopt(this.node)}}}),A.Shape=A.invent({create:function(t){this.constructor(t)},inherit:A.Element}),A.Bare=A.invent({create:function(t,e){if(this.constructor(A.create(t)),e)for(var n in e.prototype)"function"==typeof e.prototype[n]&&(this[n]=e.prototype[n])},inherit:A.Element,extend:{words:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(e.createTextNode(t)),this}}}),A.extend(A.Parent,{element:function(t,e){return this.put(new A.Bare(t,e))}}),A.Symbol=A.invent({create:"symbol",inherit:A.Container,construct:{symbol:function(){return this.put(new A.Symbol)}}}),A.Use=A.invent({create:"use",inherit:A.Shape,extend:{element:function(t,e){return this.attr("href",(e||"")+"#"+t,A.xlink)}},construct:{use:function(t,e){return this.put(new A.Use).element(t,e)}}}),A.Rect=A.invent({create:"rect",inherit:A.Shape,construct:{rect:function(t,e){return this.put(new A.Rect).size(t,e)}}}),A.Circle=A.invent({create:"circle",inherit:A.Shape,construct:{circle:function(t){return this.put(new A.Circle).rx(new A.Number(t).divide(2)).move(0,0)}}}),A.extend([A.Circle,A.FX],{rx:function(t){return this.attr("r",t)},ry:function(t){return this.rx(t)}}),A.Ellipse=A.invent({create:"ellipse",inherit:A.Shape,construct:{ellipse:function(t,e){return this.put(new A.Ellipse).size(t,e).move(0,0)}}}),A.extend([A.Ellipse,A.Rect,A.FX],{rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)}}),A.extend([A.Circle,A.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 A.Number(t).divide(2))},height:function(t){return null==t?2*this.ry():this.ry(new A.Number(t).divide(2))},size:function(t,e){var n=d(this,t,e);return this.rx(new A.Number(n.width).divide(2)).ry(new A.Number(n.height).divide(2))}}),A.Line=A.invent({create:"line",inherit:A.Shape,extend:{array:function(){return new A.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 A.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 A.Line.prototype.plot.apply(this.put(new A.Line),null!=t?[t,e,n,i]:[0,0,0,0])}}}),A.Polyline=A.invent({create:"polyline",inherit:A.Shape,construct:{polyline:function(t){return this.put(new A.Polyline).plot(t||new A.PointArray)}}}),A.Polygon=A.invent({create:"polygon",inherit:A.Shape,construct:{polygon:function(t){return this.put(new A.Polygon).plot(t||new A.PointArray)}}}),A.extend([A.Polyline,A.Polygon],{array:function(){return this._array||(this._array=new A.PointArray(this.attr("points")))},plot:function(t){return null==t?this.array():this.clear().attr("points","string"==typeof t?t:this._array=new A.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))}}),A.extend([A.Line,A.Polyline,A.Polygon],{MorphArray:A.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)}}),A.Path=A.invent({create:"path",inherit:A.Shape,extend:{MorphArray:A.PathArray,array:function(){return this._array||(this._array=new A.PathArray(this.attr("d")))},plot:function(t){return null==t?this.array():this.clear().attr("d","string"==typeof t?t:this._array=new A.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 A.Path).plot(t||new A.PathArray)}}}),A.Image=A.invent({create:"image",inherit:A.Shape,extend:{load:function(e,n){if(!e)return this;var i=new t.Image;return A.on(i,"load",function(t){var r=this.parent(A.Pattern);0===this.width()&&0===this.height()&&this.size(i.width,i.height),r instanceof A.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),A.on(i,"load error",function(){A.off(i)}),this.attr("href",i.src=e,A.xlink)}},construct:{image:function(t,e){return this.put(new A.Image).size(0,0).load(t,e)}}}),A.Text=A.invent({create:function(t){this.constructor(t||A.create("text")),this.dom.leading=new A.Number(1.3),this._rebuild=!0,this._build=!1,this.attr("font-family",A.defaults.attrs["font-family"])},inherit:A.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===A.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()},size:function(t){return this.attr("font-size",t).rebuild()},leading:function(t){return null==t?this.dom.leading:(this.dom.leading=new A.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 A.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 A.Number(t.leading||1.3),this}},construct:{text:function(t){return this.put(new A.Text).text(t)},plain:function(t){return this.put(new A.Text).plain(t)}}}),A.Tspan=A.invent({create:"tspan",inherit:A.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(A.Text);return this.dom.newLined=!0,this.dy(t.dom.leading*t.attr("font-size")).attr("x",t.x())}}}),A.extend([A.Text,A.Tspan],{plain:function(t){return!1===this._build&&this.clear(),this.node.appendChild(e.createTextNode(t)),this},tspan:function(t){var e=new A.Tspan;return this._build||this.clear(),this.node.appendChild(e.node),e.text(t)},length:function(){return this.node.getComputedTextLength()}}),A.TextPath=A.invent({create:"textPath",inherit:A.Text,parent:A.Parent,extend:{MorphArray:A.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)}}}),A.extend([A.Text],{path:function(t){var e=new A.TextPath;return t instanceof A.Path||(t=this.doc().defs().path(t)),e.attr("href","#"+t,A.xlink),this.put(e)},textPath:function(){return this.select("textPath")}}),A.extend([A.Path],{text:function(t){if(t instanceof A.Text){var e=t.text();return t.clear().path(this).text(e)}return this.parent().put(new A.Text).path(this).text(t)}}),A.Nested=A.invent({create:"svg",inherit:A.Container,construct:{nested:function(){return this.put(new A.Nested)}}}),A.A=A.invent({create:"a",inherit:A.Container,extend:{to:function(t){return this.attr("href",t,A.xlink)},target:function(t){return this.attr("target",t)}},construct:{link:function(t){return this.put(new A.A).to(t)}}}),A.extend(A.Element,{linkTo:function(t){var e=new A.A;return"function"==typeof t?t.call(e,e):e.to(t),this.parent().put(e).put(this)}}),A.Marker=A.invent({create:"marker",inherit:A.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)}}}),A.extend(A.Defs,{marker:function(t,e,n){return this.put(new A.Marker).size(t,e).ref(t/2,e/2).viewbox(0,0,t,e).attr("orient","auto").update(n)}}),A.extend([A.Line,A.Polyline,A.Polygon,A.Path],{marker:function(t,e,n,i){var r=["marker"];return"all"!==t&&r.push(t),r=r.join("-"),t=arguments[1]instanceof A.Marker?arguments[1]:this.doc().marker(e,n,i),this.attr(r,t)}});var k={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||A.Color.isRgb(n)||n&&"function"==typeof n.fill)this.attr(t,n);else for(e=k[t].length-1;e>=0;e--)null!=n[k[t][e]]&&this.attr(k.prefix(t,k[t][e]),n[k[t][e]]);return this},A.extend([A.Element,A.FX],n)}),A.extend([A.Element,A.FX],{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)},scale:function(t,e,n,i){return 1===arguments.length||3===arguments.length?this.transform({scale:t,origin:[e,n]},!0):this.transform({scaleX:t,scaleY:e,origin:[n,i]},!0)},translate:function(t,e){return this.transform({translate:[t,e]},!0)},flip:function(t,e){var n="both"===t&&isFinite(e)?[e,e]:"x"===t?[e,0]:"y"===t?[0,e]:void 0;this.transform({flip:t,origin:n})},opacity:function(t){return this.attr("opacity",t)},dx:function(t){return this.x(new A.Number(t).plus(this instanceof A.FX?0:this.x()),!0)},dy:function(t){return this.y(new A.Number(t).plus(this instanceof A.FX?0:this.y()),!0)},dmove:function(t,e){return this.dx(t).dy(e)}}),A.extend([A.Rect,A.Ellipse,A.Circle,A.Gradient,A.FX],{radius:function(t,e){var n=(this._target||this).type;return"radialGradient"===n||"radialGradient"===n?this.attr("r",new A.Number(t)):this.rx(t).ry(null==e?t:e)}}),A.extend(A.Path,{length:function(){return this.node.getTotalLength()},pointAt:function(t){return new A.Point(this.node.getPointAtLength(t))}}),A.extend([A.Parent,A.Text,A.Tspan,A.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)}}),A.extend(A.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}}),A.extend(A.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={})}}),A.get=function(t){var n=e.getElementById(y(t)||t);return A.adopt(n)},A.select=function(t,n){return A.utils.map((n||e).querySelectorAll(t),function(t){return A.adopt(t)})},A.$$=function(t,n){return A.utils.map((n||e).querySelectorAll(t),function(t){return A.adopt(t)})},A.$=function(t,n){return A.adopt((n||e).querySelector(t))},A.extend(A.Parent,{select:function(t){return A.select(t,this.node)}});var E="abcdef".split("");return A.Box=A.invent({create:function(t){var e=[0,0,0,0];t="string"==typeof t?t.split(A.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],g(this)},extend:{merge:function(t){var e=Math.min(this.x,t.x),n=Math.min(this.y,t.y);return new A.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 A.Point(this.x,this.y),new A.Point(this.x2,this.y),new A.Point(this.x,this.y2),new A.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 A.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 A.Box(t,e,n,i),this},at:function(t){return this.destination?new A.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:A.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(A.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 A.Box(t)},rbox:function(t){try{var e=new A.Box(this.node.getBoundingClientRect());return t?e.transform(t.screenCTM().inverse()):e.addOffset()}catch(t){return new A.Box}}}}),A.extend([A.Doc,A.Nested,A.Symbol,A.Image,A.Pattern,A.Marker,A.ForeignObject,A.View],{viewbox:function(t,e,n,i){return null==t?new A.Box(this.attr("viewBox")):this.attr("viewBox",new A.Box(t,e,n,i))}}),A.parser=function(){var t;return A.parser.nodes.svg.node.parentNode||(t=e.body||e.documentElement,A.parser.nodes.svg.addTo(t)),A.parser.nodes},A.parser.nodes={svg:(new A.Nested).size(2,0).css({opacity:0,position:"absolute",left:"-100%",top:"-100%",overflow:"hidden"})},A.parser.nodes.path=A.parser.nodes.svg.path().node,A}); \ No newline at end of file
diff --git a/playgrounds/transforms/transforms.html b/playgrounds/transforms/transforms.html
index 4382745..58eb5dc 100644
--- a/playgrounds/transforms/transforms.html
+++ b/playgrounds/transforms/transforms.html
@@ -12,11 +12,19 @@
<h1>SVG JS Playground</h1>
- <svg viewBox="0 0 1000 1000">
-
- <rect id="old" x=300 y=400 width=200 height=400 class="green"/>
- <rect id="new" x=300 y=400 width=200 height=400 class="pink"/>
-
+ <svg viewBox="0 0 1400 1000">
+
+ <rect id="old" x=200 y=400 width=200 height=400 class="green"/>
+ <rect id="new" x=200 y=400 width=200 height=400 class="pink"/>
+ <ellipse id="new" cx=800 cy=500 rx=10 ry=10 class="dark-pink"/>
+ <!-- <ellipse cx=0 cy=0 rx=3 ry=3 />
+ <ellipse cx=100 cy=0 rx=3 ry=3 />
+ <ellipse cx=0 cy=100 rx=3 ry=3 />
+ <ellipse cx=100 cy=100 rx=3 ry=3 />
+ <ellipse fill=red cx=0 cy=0 rx=3 ry=3 />
+ <ellipse fill=red cx=100 cy=0 rx=3 ry=3 />
+ <ellipse fill=red cx=0 cy=100 rx=3 ry=3 /> -->
+ <!-- <ellipse fill=red cx=100 cy=100 rx=3 ry=3 /> -->
</svg>
</body>
diff --git a/playgrounds/transforms/transforms.js b/playgrounds/transforms/transforms.js
index 797fa65..3b12f65 100644
--- a/playgrounds/transforms/transforms.js
+++ b/playgrounds/transforms/transforms.js
@@ -1,7 +1,20 @@
let mover = SVG.select("#new")[0]
+// mover.transform({
+// // position: [800, 500],
+// // origin: [200, 400],
+// // skew: [20, 0],
+// // rotate: 30,
+// })
-console.log(mover.transform());
-mover.transform({
- position: [30, 50]
-})
+
+// var draw = SVG.select('svg')[0]
+// var rect = draw.rect(100, 100)
+// .transform({
+// // rotate: -10,
+// translate: [-50, -50],
+// // scale: 2
+// }).opacity(0.3)
+//
+//
+// var es = SVG.select('ellipse')
diff --git a/spec/SpecRunner.html b/spec/SpecRunner.html
index 7461bdd..1ecef12 100644
--- a/spec/SpecRunner.html
+++ b/spec/SpecRunner.html
@@ -52,7 +52,7 @@
<!-- include spec files here... -->
- <script src="spec/adopter.js"></script>
+ <!-- <script src="spec/adopter.js"></script>
<script src="spec/arrange.js"></script>
<script src="spec/array.js"></script>
<script src="spec/bare.js"></script>
@@ -63,21 +63,21 @@
<script src="spec/container.js"></script>
<script src="spec/defs.js"></script>
<script src="spec/doc.js"></script>
- <script src="spec/easing.js"></script>
+ <script src="spec/easing.js"></script> -->
<script src="spec/element.js"></script>
- <script src="spec/ellipse.js"></script>
+ <!-- <script src="spec/ellipse.js"></script>
<script src="spec/event.js"></script>
<script src="spec/fx.js"></script>
<script src="spec/gradient.js"></script>
- <script src="spec/group.js"></script>
+ <script src="spec/group.js"></script>-->
<script src="spec/helper.js"></script>
- <script src="spec/hyperlink.js"></script>
+ <!-- <script src="spec/hyperlink.js"></script>
<script src="spec/image.js"></script>
<script src="spec/line.js"></script>
<script src="spec/marker.js"></script>
- <script src="spec/mask.js"></script>
+ <script src="spec/mask.js"></script> -->
<script src="spec/matrix.js"></script>
- <script src="spec/memory.js"></script>
+ <!-- <script src="spec/memory.js"></script>
<script src="spec/nested.js"></script>
<script src="spec/number.js"></script>
<script src="spec/path.js"></script>
@@ -97,7 +97,7 @@
<script src="spec/tspan.js"></script>
<script src="spec/use.js"></script>
<script src="spec/utils.js"></script>
- <script src="spec/viewbox.js"></script>
+ <script src="spec/viewbox.js"></script> -->
</body>
</html>
diff --git a/spec/spec/element.js b/spec/spec/element.js
index a5b26a1..3f62e5a 100644
--- a/spec/spec/element.js
+++ b/spec/spec/element.js
@@ -134,13 +134,13 @@ describe('Element', function() {
it('increases the global id sequence', function() {
var did = SVG.did
rect.id()
-
+
expect(did + 1).toBe(SVG.did)
})
it('adds a unique id containing the node name', function() {
var did = SVG.did
rect.id()
-
+
expect(rect.attr('id')).toBe('SvgjsRect' + did)
})
it('gets the value if the id attribute without an argument', function() {
@@ -194,23 +194,19 @@ describe('Element', function() {
rect = draw.rect(100,100)
})
- it('gets the current transformations', function() {
- expect(rect.transform()).toEqual(new SVG.Matrix(rect).extract())
+ it('gets the current transformation matrix', function() {
+ expect(rect.transform()).toEqual(new SVG.Matrix(rect))
})
it('sets the translation of and element', function() {
- rect.transform({ x: 10, y: 11 })
+ rect.transform({ translate: [10, 11] })
expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([1,0,0,1,10,11])
})
it('performs an absolute translation', function() {
- rect.transform({ x: 10, y: 11 }).transform({ x: 20, y: 21 })
+ rect.transform({ translate: [10, 11] }).transform({ translate: [20, 21] })
expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([1,0,0,1,20,21])
})
- it('performs a relative translation when relative is set to true', function() {
- rect.transform({ x: 10, y: 11 }).transform({ x: 20, y: 21, relative: true })
- expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([1,0,0,1,30,32])
- })
it('performs a relative translation with relative flag', function() {
- rect.transform({ x: 10, y: 11 }).transform({ x: 20, y: 21 }, true)
+ rect.transform({ translate: [10, 11] }).transform({ translate: [20, 21] }, true)
expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([1,0,0,1,30,32])
})
it('sets the scaleX and scaleY of an element', function() {
@@ -248,7 +244,7 @@ describe('Element', function() {
expect(ctm.f).toBe(0)
})
it('sets the skewX of an element with given center', function() {
- ctm = rect.transform({ skewX: 10, cx: 0, cy: 0 }).ctm()
+ ctm = rect.transform({ skewX: 10, ox: 0, oy: 0 }).ctm()
expect(ctm.a).toBe(1)
expect(ctm.b).toBe(0)
expect(ctm.c).toBeCloseTo(0.17632698070846498)
@@ -257,7 +253,7 @@ describe('Element', function() {
expect(ctm.f).toBe(0)
})
it('sets the skewY of an element', function() {
- ctm = rect.transform({ skewY: -10, cx: 0, cy: 0 }).ctm()
+ ctm = rect.transform({ skewY: -10, ox: 0, oy: 0 }).ctm()
expect(ctm.a).toBe(1)
expect(ctm.b).toBeCloseTo(-0.17632698070846498)
expect(ctm.c).toBe(0)
@@ -266,7 +262,7 @@ describe('Element', function() {
expect(ctm.f).toBe(0)
})
it('sets the skewX and skewY of an element', function() {
- ctm = rect.transform({ skewX: 10, skewY: -10, cx: 0, cy: 0 }).ctm()
+ ctm = rect.transform({ skewX: 10, skewY: -10, ox: 0, oy: 0 }).ctm()
expect(ctm.a).toBe(1)
expect(ctm.b).toBeCloseTo(-0.17632698070846498)
expect(ctm.c).toBeCloseTo(0.17632698070846498)
@@ -275,7 +271,7 @@ describe('Element', function() {
expect(ctm.f).toBe(0)
})
it('performs a uniform skew with skew given', function() {
- ctm = rect.transform({ skew: 5, cx: 0, cy: 0 }).ctm()
+ ctm = rect.transform({ skew: 5, ox: 0, oy: 0 }).ctm()
expect(ctm.a).toBe(1)
expect(ctm.b).toBeCloseTo(0.08748866352592401)
expect(ctm.c).toBeCloseTo(0.08748866352592401)
@@ -284,17 +280,16 @@ describe('Element', function() {
expect(ctm.f).toBe(0)
})
it('rotates the element around its centre if no rotation point is given', function() {
- ctm = rect.center(100, 100).transform({ rotation: 45 }).ctm()
+ ctm = rect.center(100, 100).transform({ rotate: 45 }).ctm()
expect(ctm.a).toBeCloseTo(0.7071068286895752)
expect(ctm.b).toBeCloseTo(0.7071068286895752)
expect(ctm.c).toBeCloseTo(-0.7071068286895752)
expect(ctm.d).toBeCloseTo(0.7071068286895752)
expect(ctm.e).toBeCloseTo(100)
expect(ctm.f).toBeCloseTo(-41.421356201171875)
- expect(rect.transform('rotation')).toBe(45)
})
it('rotates the element around the given rotation point', function() {
- ctm = rect.transform({ rotation: 55, cx: 80, cy:2 }).ctm()
+ ctm = rect.transform({ rotate: 55, origin: [80, 2] }).ctm()
expect(ctm.a).toBeCloseTo(0.5735765099525452)
expect(ctm.b).toBeCloseTo(0.8191521167755127)
expect(ctm.c).toBeCloseTo(-0.8191521167755127)
@@ -315,15 +310,15 @@ describe('Element', function() {
expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([-1,0,0,1,100,0])
})
it('flips the element on x axis with offset', function() {
- rect.transform({ flip: 'x', offset: 20 })
+ rect.transform({ flip: 'x', origin: [20, 0] })
expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([-1,0,0,1,40,0])
})
it('flips the element on y axis with offset', function() {
- rect.transform({ flip: 'y', offset: 20 })
+ rect.transform({ flip: 'y', origin: [0, 20] })
expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([1,0,0,-1,0,40])
})
it('flips the element on both axis with offset', function() {
- rect.transform({ flip: 'both', offset: 20 })
+ rect.transform({ flip: 'both', origin: [20, 20] })
expect(window.matrixStringToArray(rect.node.getAttribute('transform'))).toEqual([-1,0,0,-1,40,40])
})
it('flips the element on both axis', function() {
@@ -386,6 +381,20 @@ describe('Element', function() {
rect.attr('transform', 'translate(24,14) , translate(36,6)')
expect(rect.matrixify().toString()).toBe('matrix(1,0,0,1,60,20)')
})
+
+
+ it('merges non-commutative transformations correctly', function() {
+ // Spaces before the comma
+ rect.attr('transform', 'scale(3, 2) translate(20,16)')
+ expect(rect.matrixify().toString()).toBe('matrix(3,0,0,2,60,32)')
+ })
+
+ it('doesn\'t care if you have matrices there', function() {
+ // Spaces before the comma
+ rect.attr('transform', 'matrix(3, 0, 0, 2, 0, 0) translate(20,16)')
+ expect(rect.matrixify().toString()).toBe('matrix(3,0,0,2,60,32)')
+ })
+
})
describe('toParent()', function() {
diff --git a/spec/spec/helper.js b/spec/spec/helper.js
index 3dd6aff..4c15acd 100644
--- a/spec/spec/helper.js
+++ b/spec/spec/helper.js
@@ -16,17 +16,17 @@ if(typeof exports === 'object'){
for(var i in attrs){
el.setAttribute(i, attrs[i])
}
-
+
for(var i in children){
if(typeof children[i] == 'string')
children[i] = document.createTextNode(children[i])
-
+
el.appendChild(children[i])
}
-
+
return el
}
-
+
// create fixtures in svgdom
var el = tag('svg', {
height:0,
@@ -122,9 +122,9 @@ if(typeof exports === 'object'){
tag('polygon', {points: '200,10 250,190 160,210'}),
tag('polyline', {points: '20,20 40,25 60,40 80,120 120,140 200,180'})
])
-
+
document.appendChild(el)
-
+
}else{
drawing = document.createElement('div')
document.getElementsByTagName('body')[0].appendChild(drawing)
diff --git a/spec/spec/matrix.js b/spec/spec/matrix.js
index 0816f66..08e0280 100644
--- a/spec/spec/matrix.js
+++ b/spec/spec/matrix.js
@@ -18,27 +18,26 @@ describe('Matrix', function() {
expect(matrix.f).toBe(0)
})
- describe('extract()', function() {
- var extract
+ describe('decompose()', function() {
+ var decompose
beforeEach(function() {
- extract = matrix.extract()
+ decompose = matrix.decompose()
})
it('parses translation values', function() {
- expect(extract.x).toBe(0)
- expect(extract.y).toBe(0)
+ expect(decompose.translateX).toBe(0)
+ expect(decompose.translateY).toBe(0)
})
- it('parses skew values', function() {
- expect(extract.skewX).toBe(0)
- expect(extract.skewY).toBe(0)
+ it('parses shear values', function() {
+ expect(decompose.shear).toBe(0)
})
it('parses scale values', function() {
- expect(extract.scaleX).toBe(1)
- expect(extract.scaleY).toBe(1)
+ expect(decompose.scaleX).toBe(1)
+ expect(decompose.scaleY).toBe(1)
})
it('parses rotatoin value', function() {
- expect(extract.rotation).toBe(0)
+ expect(decompose.rotate).toBe(0)
})
})
@@ -53,48 +52,24 @@ describe('Matrix', function() {
var rect
beforeEach(function() {
+ // Draw is defined in helpers
rect = draw.rect(100, 100)
- .transform({ rotation: -10 }, true)
- .transform({ x: 40, y: 50 }, true)
- .transform({ scale: 2 }, true)
-
+ .transform({
+ rotate: -10,
+ translate: [40, 50],
+ scale: 2,
+ })
matrix = new SVG.Matrix(rect)
})
it('parses the current transform matrix from an element', function() {
- expect(matrix.a).toBeCloseTo(1.9696155786514282)
- expect(matrix.b).toBeCloseTo(-0.3472963869571686)
- expect(matrix.c).toBeCloseTo(0.3472963869571686)
- expect(matrix.d).toBeCloseTo(1.9696155786514282)
- expect(matrix.e).toBeCloseTo(-17.770875930786133)
- expect(matrix.f).toBeCloseTo(11.178505897521973)
- })
-
- describe('extract()', function() {
-
- it('parses translation values', function() {
- var extract = new SVG.Matrix(draw.rect(100, 100).translate(40, 50)).extract()
- expect(extract.x).toBeCloseTo(40)
- expect(extract.y).toBeCloseTo(50)
- })
- it('parses skewX value', function() {
- var extract = new SVG.Matrix(draw.rect(100, 100).skew(25, 0)).extract()
- expect(extract.skewX).toBeCloseTo(25)
- })
- it('parses skewY value', function() {
- var extract = new SVG.Matrix(draw.rect(100, 100).skew(0, 20)).extract()
- expect(extract.skewY).toBeCloseTo(20)
- })
- it('parses scale values', function() {
- var extract = new SVG.Matrix(draw.rect(100, 100).scale(2, 3)).extract()
- expect(extract.scaleX).toBeCloseTo(2)
- expect(extract.scaleY).toBeCloseTo(3)
- })
- it('parses rotatoin value', function() {
- var extract = new SVG.Matrix(draw.rect(100, 100).rotate(-100)).extract()
- expect(extract.rotation).toBeCloseTo(-100)
- })
+ expect(matrix.a).toBeCloseTo(1.969615506024416)
+ expect(matrix.b).toBeCloseTo(-0.34729635533386066)
+ expect(matrix.c).toBeCloseTo(0.34729635533386066)
+ expect(matrix.d).toBeCloseTo(1.969615506024416)
+ expect(matrix.e).toBeCloseTo(-25.84559306791384)
+ expect(matrix.f).toBeCloseTo(18.884042465472234)
})
})
@@ -201,20 +176,21 @@ describe('Matrix', function() {
describe('multiply()', function() {
it('multiplies two matices', function() {
- var matrix1 = new SVG.Matrix(2, 0, 0, 5, 0, 0)
- , matrix2 = new SVG.Matrix(1, 0, 0, 1, 4, 3)
+ var matrix1 = new SVG.Matrix(1, 4, 2, 5, 3, 6)
+ , matrix2 = new SVG.Matrix(7, 8, 8, 7, 9, 6)
, matrix3 = matrix1.multiply(matrix2)
- expect(matrix1.toString()).toBe('matrix(2,0,0,5,0,0)')
- expect(matrix2.toString()).toBe('matrix(1,0,0,1,4,3)')
- expect(matrix3.toString()).toBe('matrix(2,0,0,5,8,15)')
+ expect(matrix1.toString()).toBe('matrix(1,4,2,5,3,6)')
+ expect(matrix2.toString()).toBe('matrix(7,8,8,7,9,6)')
+ expect(matrix3.toString()).toBe('matrix(23,68,22,67,24,72)')
})
+
it('accepts matrices in any form', function() {
- var matrix1 = new SVG.Matrix(2, 0, 0, 5, 0, 0)
- , matrix2 = matrix1.multiply('1,0,0,1,4,3')
+ var matrix1 = new SVG.Matrix(1, 4, 2, 5, 3, 6)
+ , matrix2 = matrix1.multiply('7,8,8,7,9,6')
- expect(matrix1.toString()).toBe('matrix(2,0,0,5,0,0)')
- expect(matrix2.toString()).toBe('matrix(2,0,0,5,8,15)')
+ expect(matrix1.toString()).toBe('matrix(1,4,2,5,3,6)')
+ expect(matrix2.toString()).toBe('matrix(23,68,22,67,24,72)')
})
})
@@ -236,10 +212,15 @@ describe('Matrix', function() {
describe('translate()', function() {
it('translates matrix by given x and y values', function() {
var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).translate(10, 12.5)
-
expect(matrix.e).toBe(14)
expect(matrix.f).toBe(15.5)
})
+
+ it('does nothing if you give it no x or y value', function() {
+ var matrix = new SVG.Matrix(1, 2, 3, 4, 5, 6).translate()
+ expect(matrix.e).toBe(5)
+ expect(matrix.f).toBe(6)
+ })
})
describe('scale()', function() {
@@ -248,51 +229,59 @@ describe('Matrix', function() {
expect(matrix.a).toBe(3)
expect(matrix.d).toBe(3)
- expect(matrix.e).toBe(4)
- expect(matrix.f).toBe(3)
+ expect(matrix.e).toBe(4 * 3)
+ expect(matrix.f).toBe(3 * 3)
})
it('performs a non-uniformal scale with two values', function() {
var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).scale(2.5, 3.5)
expect(matrix.a).toBe(2.5)
expect(matrix.d).toBe(3.5)
- expect(matrix.e).toBe(4)
- expect(matrix.f).toBe(3)
+ expect(matrix.e).toBe(4 * 2.5)
+ expect(matrix.f).toBe(3 * 3.5)
})
it('performs a uniformal scale at a given center point with three values', function() {
- var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).scale(3, 150, 100)
+ var matrix = new SVG.Matrix(1, 3, 2, 3, 4, 3).scale(3, 2, 3)
expect(matrix.a).toBe(3)
- expect(matrix.d).toBe(3)
- expect(matrix.e).toBe(-296)
- expect(matrix.f).toBe(-197)
+ expect(matrix.b).toBe(9)
+ expect(matrix.c).toBe(6)
+ expect(matrix.d).toBe(9)
+ expect(matrix.e).toBe(8)
+ expect(matrix.f).toBe(3)
})
it('performs a non-uniformal scale at a given center point with four values', function() {
- var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).scale(3, 2, 150, 100)
+ var matrix = new SVG.Matrix(1, 3, 2, 3, 4, 3).scale(3, 2, 2, 3)
expect(matrix.a).toBe(3)
- expect(matrix.d).toBe(2)
- expect(matrix.e).toBe(-296)
- expect(matrix.f).toBe(-97)
+ expect(matrix.b).toBe(6)
+ expect(matrix.c).toBe(6)
+ expect(matrix.d).toBe(6)
+ expect(matrix.e).toBe(8)
+ expect(matrix.f).toBe(3)
})
})
describe('rotate()', function() {
it('performs a rotation with one argument', function() {
- var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).rotate(30)
+ var matrix = new SVG.Matrix(1, 3, 2, 3, 4, 3).rotate(30)
- expect(matrix.a).toBeCloseTo(0.8660254037844387)
- expect(matrix.d).toBeCloseTo(0.8660254037844387)
- expect(matrix.e).toBe(4)
- expect(matrix.f).toBe(3)
+ expect(matrix.a).toBeCloseTo(-0.6339746)
+ expect(matrix.b).toBeCloseTo(3.09807621)
+ expect(matrix.c).toBeCloseTo(0.23205081)
+ expect(matrix.d).toBeCloseTo(3.59807621)
+ expect(matrix.e).toBeCloseTo(1.96410162)
+ expect(matrix.f).toBeCloseTo(4.59807621)
})
- it('performs a rotation on a given point with three arguments', function() {
- var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).rotate(30, 150, 100)
+ it('performs a rotation around a given point with three arguments', function() {
+ var matrix = new SVG.Matrix(1, 3, 2, 3, 4, 3).rotate(30, 2, 3)
- expect(matrix.a).toBeCloseTo(0.8660254037844387)
- expect(matrix.d).toBeCloseTo(0.8660254037844387)
- expect(matrix.e).toBeCloseTo(74.0961894323342)
- expect(matrix.f).toBeCloseTo(-58.60254037844388)
+ expect(matrix.a).toBeCloseTo(-0.633974596216)
+ expect(matrix.b).toBeCloseTo(3.09807621135)
+ expect(matrix.c).toBeCloseTo(0.232050807569)
+ expect(matrix.d).toBeCloseTo(3.59807621135)
+ expect(matrix.e).toBeCloseTo(3.73205080757)
+ expect(matrix.f).toBeCloseTo(4.0)
})
})
@@ -303,7 +292,7 @@ describe('Matrix', function() {
expect(matrix.a).toBe(-1)
expect(matrix.d).toBe(1)
- expect(matrix.e).toBe(4)
+ expect(matrix.e).toBe(-4)
expect(matrix.f).toBe(3)
})
it('performs a flip over the horizontal axis over a given point with two arguments', function() {
@@ -311,7 +300,7 @@ describe('Matrix', function() {
expect(matrix.a).toBe(-1)
expect(matrix.d).toBe(1)
- expect(matrix.e).toBe(304)
+ expect(matrix.e).toBe(296)
expect(matrix.f).toBe(3)
})
})
@@ -322,7 +311,7 @@ describe('Matrix', function() {
expect(matrix.a).toBe(1)
expect(matrix.d).toBe(-1)
expect(matrix.e).toBe(4)
- expect(matrix.f).toBe(3)
+ expect(matrix.f).toBe(-3)
})
it('performs a flip over the vertical axis over a given point with two arguments', function() {
var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).flip('y', 100)
@@ -330,7 +319,7 @@ describe('Matrix', function() {
expect(matrix.a).toBe(1)
expect(matrix.d).toBe(-1)
expect(matrix.e).toBe(4)
- expect(matrix.f).toBe(203)
+ expect(matrix.f).toBe(197)
})
})
describe('with no axis given', function() {
@@ -339,126 +328,129 @@ describe('Matrix', function() {
expect(matrix.a).toBe(-1)
expect(matrix.d).toBe(-1)
- expect(matrix.e).toBe(4)
- expect(matrix.f).toBe(3)
+ expect(matrix.e).toBe(-4)
+ expect(matrix.f).toBe(-3)
})
it('performs a flip over the horizontal and vertical axis over a given point with one argument that represent both coordinates', function() {
var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).flip(100)
expect(matrix.a).toBe(-1)
expect(matrix.d).toBe(-1)
- expect(matrix.e).toBe(204)
- expect(matrix.f).toBe(203)
+ expect(matrix.e).toBe(196)
+ expect(matrix.f).toBe(197)
})
it('performs a flip over the horizontal and vertical axis over a given point with two arguments', function() {
var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).flip(50, 100)
expect(matrix.a).toBe(-1)
expect(matrix.d).toBe(-1)
- expect(matrix.e).toBe(104)
- expect(matrix.f).toBe(203)
+ expect(matrix.e).toBe(96)
+ expect(matrix.f).toBe(197)
})
})
})
describe('skew()', function() {
it('performs a uniformal skew with one value', function() {
- var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(14)
+ var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(30)
expect(matrix.a).toBe(1)
- expect(matrix.b).toBeCloseTo(0.24932800284318)
- expect(matrix.c).toBeCloseTo(0.24932800284318)
+ expect(matrix.b).toBeCloseTo(0.57735026919)
+ expect(matrix.c).toBeCloseTo(0.57735026919)
expect(matrix.d).toBe(1)
- expect(matrix.e).toBe(4)
- expect(matrix.f).toBe(3)
+ expect(matrix.e).toBeCloseTo(5.73205080757)
+ expect(matrix.f).toBeCloseTo(5.30940107676)
})
+
it('performs a non-uniformal skew with two values', function() {
- var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(8, 5)
+ var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(30, 20)
expect(matrix.a).toBe(1)
- expect(matrix.b).toBeCloseTo(0.087488663525924)
- expect(matrix.c).toBeCloseTo(0.14054083470239)
+ expect(matrix.b).toBeCloseTo(0.363970234266)
+ expect(matrix.c).toBeCloseTo(0.57735026919)
expect(matrix.d).toBe(1)
- expect(matrix.e).toBe(4)
- expect(matrix.f).toBe(3)
+ expect(matrix.e).toBeCloseTo(5.73205080757)
+ expect(matrix.f).toBeCloseTo(4.45588093706)
})
+
it('performs a uniformal skew at a given center point with three values', function() {
- var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(3, 150, 100)
+ var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(30, 150, 100)
expect(matrix.a).toBe(1)
- expect(matrix.b).toBeCloseTo(0.052407779283041)
- expect(matrix.c).toBeCloseTo(0.052407779283041)
+ expect(matrix.b).toBeCloseTo(0.57735026919)
+ expect(matrix.c).toBeCloseTo(0.57735026919)
expect(matrix.d).toBe(1)
- expect(matrix.e).toBeCloseTo(-1.2407779283)
- expect(matrix.f).toBeCloseTo(-4.8611668924562)
+ expect(matrix.e).toBeCloseTo(-52.0029761114)
+ expect(matrix.f).toBeCloseTo(-81.2931393017)
})
+
it('performs a non-uniformal skew at a given center point with four values', function() {
- var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(9, 7, 150, 100)
+ var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(30, 20, 150, 100)
- expect(matrix.a).toBe(1)
- expect(matrix.b).toBeCloseTo(0.1227845609029)
- expect(matrix.c).toBeCloseTo(0.15838444032454)
- expect(matrix.d).toBe(1)
- expect(matrix.e).toBeCloseTo(-11.83844403245)
- expect(matrix.f).toBeCloseTo(-15.417684135435)
+ expect(matrix.a).toBe(1.0)
+ expect(matrix.b).toBeCloseTo(0.363970234266)
+ expect(matrix.c).toBeCloseTo(0.57735026919)
+ expect(matrix.d).toBe(1.0)
+ expect(matrix.e).toBeCloseTo(-52.0029761114)
+ expect(matrix.f).toBeCloseTo(-50.1396542029)
})
- it('can be chained', function(){
- var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(9, 7).skew(20, 40)
- expect(matrix.a).toBeCloseTo(1.1329003254605)
- expect(matrix.b).toBeCloseTo(0.96188419208018)
- expect(matrix.c).toBeCloseTo(0.52235467459074)
- expect(matrix.d).toBeCloseTo(1.0446899253961)
- expect(matrix.e).toBe(4)
- expect(matrix.f).toBe(3)
+ it('can be chained', function(){
+ var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skew(20, 30).skew(30, 20)
+ expect(matrix.a).toBeCloseTo(1.33333333333)
+ expect(matrix.b).toBeCloseTo(0.941320503456)
+ expect(matrix.c).toBeCloseTo(0.941320503456)
+ expect(matrix.d).toBeCloseTo(1.13247433143)
+ expect(matrix.e).toBeCloseTo(8.1572948437)
+ expect(matrix.f).toBeCloseTo(7.16270500812)
})
})
describe('skewX', function(){
it('performs a skew along the x axis with one value', function() {
- var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewX(12)
+ var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewX(30)
expect(matrix.a).toBe(1)
expect(matrix.b).toBe(0)
- expect(matrix.c).toBeCloseTo(0.21255656167002)
+ expect(matrix.c).toBeCloseTo(0.57735026919)
expect(matrix.d).toBe(1)
- expect(matrix.e).toBe(4)
+ expect(matrix.e).toBeCloseTo(5.73205080757)
expect(matrix.f).toBe(3)
})
it('performs a skew along the x axis at a given center point with three values', function() {
- var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewX(5, 150, 100)
+ var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewX(30, 150, 100)
expect(matrix.a).toBe(1)
expect(matrix.b).toBe(0)
- expect(matrix.c).toBeCloseTo(0.087488663525924)
+ expect(matrix.c).toBeCloseTo(0.57735026919)
expect(matrix.d).toBe(1)
- expect(matrix.e).toBeCloseTo(-4.74886635259)
+ expect(matrix.e).toBeCloseTo(-52.0029761114)
expect(matrix.f).toBe(3)
})
})
describe('skewY', function(){
it('performs a skew along the y axis with one value', function() {
- var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewY(12)
+ var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewY(30)
expect(matrix.a).toBe(1)
- expect(matrix.b).toBeCloseTo(0.21255656167002)
+ expect(matrix.b).toBeCloseTo(0.57735026919)
expect(matrix.c).toBe(0)
expect(matrix.d).toBe(1)
expect(matrix.e).toBe(4)
- expect(matrix.f).toBe(3)
+ expect(matrix.f).toBeCloseTo(5.30940107676)
})
it('performs a skew along the y axis at a given center point with three values', function() {
- var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewY(5, 150, 100)
+ var matrix = new SVG.Matrix(1, 0, 0, 1, 4, 3).skewY(30, 150, 100)
expect(matrix.a).toBe(1)
- expect(matrix.b).toBeCloseTo(0.087488663525924)
+ expect(matrix.b).toBeCloseTo(0.57735026919)
expect(matrix.c).toBe(0)
expect(matrix.d).toBe(1)
expect(matrix.e).toBe(4)
- expect(matrix.f).toBeCloseTo(-10.123299528889)
+ expect(matrix.f).toBeCloseTo(-81.2931393017)
})
})
diff --git a/src/boxes.js b/src/boxes.js
index a5ca1e8..cd90207 100644
--- a/src/boxes.js
+++ b/src/boxes.js
@@ -18,6 +18,7 @@ SVG.Box = SVG.invent({
// add center, right, bottom...
fullBox(this)
},
+
extend: {
// Merge rect box with another, return a new instance
merge: function (box) {
@@ -52,11 +53,7 @@ SVG.Box = SVG.invent({
yMax = Math.max(yMax, p.y)
})
- return new SVG.Box(
- xMin, yMin,
- xMax - xMin,
- yMax - yMin
- )
+ return new SVG.Box(xMin, yMin, xMax - xMin, yMax - yMin)
},
addOffset: function () {
@@ -65,9 +62,11 @@ SVG.Box = SVG.invent({
this.y += window.pageYOffset
return this
},
+
toString: function () {
return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height
},
+
morph: function (x, y, width, height) {
this.destination = new SVG.Box(x, y, width, height)
return this
@@ -77,15 +76,15 @@ SVG.Box = SVG.invent({
if (!this.destination) return this
return new SVG.Box(
- this.x + (this.destination.x - this.x) * pos
- , this.y + (this.destination.y - this.y) * pos
- , this.width + (this.destination.width - this.width) * pos
- , this.height + (this.destination.height - this.height) * pos
+ this.x + (this.destination.x - this.x) * pos,
+ this.y + (this.destination.y - this.y) * pos,
+ this.width + (this.destination.width - this.width) * pos,
+ this.height + (this.destination.height - this.height) * pos
)
}
},
- // Define Parent
+ // Define Parent
parent: SVG.Element,
// Constructor
diff --git a/src/helpers.js b/src/helpers.js
index 56565a0..16e6e4e 100644
--- a/src/helpers.js
+++ b/src/helpers.js
@@ -217,9 +217,13 @@ function mag (a, b) {
// Given a coordinate (a, b), this will calculate the sin, cosine and angle
// of this point projected onto the unit circle directly
function unitCircle (a, b) {
- var len = Math.sqrt(a * a + b * b)
- var cos = a / len
- var sin = b / len
- var theta = Math.atan2(b, a) * 180 / Math.PI
- return {theta: theta, cos: cos, sin: sin}
+ var thetaRad = Math.atan2(b, a)
+ var thetaDeg = thetaRad * 180 / Math.PI
+ var cos = Math.cos(thetaRad)
+ var sin = Math.sin(thetaRad)
+ return {theta: thetaDeg, cos: cos, sin: sin}
+}
+
+function closeEnough (a, b, threshold) {
+ return Math.abs (b - a) < (threshold || 1e-6)
}
diff --git a/src/line.js b/src/line.js
index 100d625..da0c0ca 100644
--- a/src/line.js
+++ b/src/line.js
@@ -16,6 +16,7 @@ SVG.Line = SVG.invent({
[ this.attr('x2'), this.attr('y2') ]
])
},
+
// Overwrite native plot() method
plot: function (x1, y1, x2, y2) {
if (x1 == null) {
@@ -28,10 +29,12 @@ SVG.Line = SVG.invent({
return this.attr(x1)
},
+
// Move by left top corner
move: function (x, y) {
return this.attr(this.array().move(x, y).toLine())
},
+
// Set element size to given width and height
size: function (width, height) {
var p = proportionalSize(this, width, height)
diff --git a/src/matrix.js b/src/matrix.js
index a7676da..970f6ed 100644
--- a/src/matrix.js
+++ b/src/matrix.js
@@ -25,137 +25,71 @@ SVG.Matrix = SVG.invent({
// Add methods
extend: {
- // Convert an object of affine parameters into a matrix
- compose: function (o, cx, cy) {
- // Set the defaults
- var tx = o.translateX || 0
- var ty = o.translateY || 0
- var theta = o.theta || 0
- var sx = o.scaleX || 1
- var sy = o.scaleY || 1
- var lam = o.shear || 0
- cx = cx || 0
- cy = cy || 0
-
- // Calculate the trigonometric values
- var ct = Math.cos(theta * Math.PI / 180)
- var st = Math.sin(theta * Math.PI / 180)
-
- // Calculate the matrix components directly
- var a = sx * ct
- var b = sx * st
- var c = lam * sx * ct - sy * st
- var d = lam * sx * st + sy * ct
- var e = -sx * ct * (cx + cy * lam) + sy * st * cy + tx + cx
- var f = -sx * st * (cx + cy * lam) - sy * ct * cy + ty + cy
-
- // Construct a new matrix and return it
- var matrix = new SVG.Matrix([a, b, c, d, e, f])
- return matrix
- },
- // Decompose a matrix into the affine parameters needed to form it
- decompose: function (matrix, cx, cy) {
- // Get the paramaters of the current matrix
- var a = matrix.a
- var b = matrix.b
- var c = matrix.c
- var d = matrix.d
- var e = matrix.e
- var f = matrix.f
-
- // Project the first basis vector onto the unit circle
- var circle = unitCircle(a, b)
- var theta = circle.theta
- var ct = circle.cos
- var st = circle.sin
-
- // Work out the transformation parameters
- var signX = Math.sign(a * ct + b * st)
- var sx = signX * mag(a, b)
- var lam = (st * d + ct * c) / (ct * a + st * b)
- var sy = mag(lam * a - c, d - lam * b)
- var tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy)
- var ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy)
-
- // Package and return the parameters
- return {
-
- // Bundle the affine parameters
- translateX: tx,
- translateY: ty,
- theta: theta,
- scaleX: sx,
- scaleY: sy,
- shear: lam,
-
- // Bundle the matrix parameters
- a: this.a,
- b: this.b,
- c: this.c,
- d: this.d,
- e: this.e,
- f: this.f,
-
- // Return the new origin point
- x: this.e,
- y: this.f,
- matrix: new SVG.Matrix(this)
- }
+ clone: function () {
+ return new SVG.Matrix(this)
},
+
// Clone matrix
- form: function (o) {
+ affine: function (o) {
// 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
- var skewX = o.skew.length ? o.skew[0]
+ var skewX = o.skew && o.skew.length ? o.skew[0]
: isFinite(o.skew) ? o.skew
: isFinite(o.skewX) ? o.skewX
: 0
- var skewY = o.skew.length ? o.skew[1]
+ var skewY = o.skew && o.skew.length ? o.skew[1]
: isFinite(o.skew) ? o.skew
: isFinite(o.skewY) ? o.skewY
: 0
- var sx = o.scale.length ? o.scale[0] * flipX
+ var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX
: isFinite(o.scale) ? o.scale * flipX
: isFinite(o.scaleX) ? o.scaleX * flipX
: flipX
- var sy = o.scale.length ? o.scale[1] * flipY
+ var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY
: isFinite(o.scale) ? o.scale * flipY
: isFinite(o.scaleY) ? o.scaleY * flipY
: flipY
- var kx = Math.tan(SVG.utils.radians(skewX))
- var ky = Math.tan(SVG.utils.radians(skewY))
- var lam = o.shear || 0
- var theta = SVG.utils.radians(o.rotate || 0)
- var st = Math.sin(theta)
- var ct = Math.cos(theta)
- var ox = o.origin.length ? o.origin[0] : o.ox || 0
- var oy = o.origin.length ? o.origin[1] : o.oy || 0
- var px = o.position.length ? o.position[0] : o.px || ox
- var py = o.position.length ? o.position[1] : o.py || oy
- var tx = o.translate.length ? o.translate[0] : o.tx || 0
- var ty = o.translate.length ? o.translate[1] : o.ty || 0
-
- // Form the matrix parameters... aka. welcome to wonderland! (used wolfram)
- var a = ct * sx + ky * st * sy
- var b = ct * ky * sy - st * sx
- var c = ct * kx * sx + st * sy + lam * (ct * sx + ky * st * sy)
- var d = -kx * st * sx + ct * sy + lam * (-st * sx + ct * ky * sy)
- var e = px + tx + ox * (ct * sx + ky * st * sy) + oy * (ct * kx * sx + st * sy + lam * (ct * sx + ky * st * sy))
- var f = py + ty + ox * (-st * sx + ct * ky * sy) + oy * (-kx * st * sx + ct * sy + lam * (-st * sx + ct * ky * sy))
- var result = new SVG.Matrix(a, b, c, d, e, f)
- return result
- },
- clone: function () {
- return new SVG.Matrix(this)
+ var shear = o.shear || 0
+ var theta = o.rotate || 0
+ var ox = o.origin && o.origin.length ? o.origin[0] : o.ox || 0
+ var oy = o.origin && o.origin.length ? o.origin[1] : o.oy || 0
+ var px = o.position && o.position.length ? o.position[0] : o.px
+ var py = o.position && o.position.length ? o.position[1] : o.py
+ var tx = o.translate && o.translate.length ? o.translate[0] : o.tx || 0
+ var ty = o.translate && o.translate.length ? o.translate[1] : o.ty || 0
+
+ // Construct the resulting matrix
+ var transformer = new SVG.Matrix()
+ .translate(-ox, -oy)
+ .scale(scaleX, scaleY)
+ .skew(skewX, skewY)
+ .shear(shear)
+ .rotate(theta)
+ .translate(ox, oy)
+ .translate(tx, ty)
+ .lmultiply(new SVG.Matrix(this))
+
+ // If we want the origin at a particular place, we force it there
+ if (isFinite(px) && isFinite(py)) {
+ // Figure out where the origin went and the delta to get there
+ var p = new SVG.Point(ox - tx, oy - ty).transform(transformer)
+ var dx = px - p.x
+ var dy = py - p.y
+
+ // Apply another translation
+ transformer = transformer.translate(dx, dy)
+ }
+ return transformer
},
+
// Morph one matrix into another
morph: function (matrix) {
// store new destination
this.destination = new SVG.Matrix(matrix)
-
return this
},
+
// Get morphed matrix at a given position
at: function (pos) {
// make sure a destination is defined
@@ -173,20 +107,44 @@ SVG.Matrix = SVG.invent({
return matrix
},
- // Multiplies by given matrix
+
+ // Left multiplies by the given matrix
multiply: function (matrix) {
- return new SVG.Matrix(this.native().multiply(parseMatrix(matrix).native()))
+ // Get the matrices
+ var l = this
+ var r = parseMatrix(matrix)
+
+ // Work out the product directly
+ var a = l.a * r.a + l.c * r.b
+ var b = l.b * r.a + l.d * r.b
+ var c = l.a * r.c + l.c * r.d
+ var d = l.b * r.c + l.d * r.d
+ var e = l.e + l.a * r.e + l.c * r.f
+ var f = l.f + l.b * r.e + l.d * r.f
+
+ // Form the matrix and return it
+ var product = new SVG.Matrix(a, b, c, d, e, f)
+ return product
},
+
+ lmultiply: function (matrix) {
+ var l = parseMatrix(matrix)
+ return l.multiply(this)
+ },
+
// Inverses matrix
inverse: function () {
return new SVG.Matrix(this.native().inverse())
},
+
// Translate matrix
translate: function (x, y) {
- var translation = new SVG.Matrix(this.native().translate(x || 0, y || 0))
- var matrix = this.multiply(translation)
- return matrix
+ var translation = new SVG.Matrix(this)
+ translation.e += x || 0
+ translation.f += y || 0
+ return translation
},
+
// Scale matrix
scale: function (x, y, cx, cy) {
// Support uniform scaling
@@ -200,10 +158,10 @@ SVG.Matrix = SVG.invent({
// Rotate the current matrix
var scale = new SVG.Matrix(x, 0, 0, y, 0, 0)
- var centered = this.around(cx, cy, scale)
- var matrix = this.multiply(centered)
+ var matrix = this.around(cx, cy, scale)
return matrix
},
+
// Rotate matrix
rotate: function (r, cx, cy) {
// Convert degrees to radians
@@ -211,23 +169,25 @@ SVG.Matrix = SVG.invent({
// Construct the rotation matrix
var rotation = new SVG.Matrix(Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0)
- var centered = this.around(cx, cy, rotation)
- var matrix = this.multiply(centered)
+ var matrix = this.around(cx, cy, rotation)
return matrix
},
+
// Flip matrix on x or y, at a given offset
- flip: function (a, o) {
- return a === 'x' ? this.scale(-1, 1, o, 0)
- : a === 'y' ? this.scale(1, -1, 0, o)
- : this.scale(-1, -1, a, o != null ? o : a)
+ flip: function (axis, around) {
+ return axis === 'x' ? this.scale(-1, 1, around, 0)
+ : axis === 'y' ? this.scale(1, -1, 0, around)
+ : this.scale(-1, -1, axis, around || axis) // Define an x, y flip point
},
- // Skew
+
+ // Shear matrix
shear: function (a, cx, cy) {
var shear = new SVG.Matrix(1, a, 0, 1, 0, 0)
- var centered = this.around(cx, cy, shear)
- var matrix = this.multiply(centered)
+ var matrix = this.around(cx, cy, shear)
return matrix
},
+
+ // Skew Matrix
skew: function (x, y, cx, cy) {
// support uniformal skew
if (arguments.length === 1) {
@@ -244,25 +204,27 @@ SVG.Matrix = SVG.invent({
// Construct the matrix
var skew = new SVG.Matrix(1, Math.tan(y), Math.tan(x), 1, 0, 0)
- var centered = this.around(cx, cy, skew)
- var matrix = this.multiply(centered)
+ var matrix = this.around(cx, cy, skew)
return matrix
},
+
// SkewX
skewX: function (x, cx, cy) {
return this.skew(x, 0, cx, cy)
},
+
// SkewY
skewY: function (y, cx, cy) {
return this.skew(0, y, cx, cy)
},
+
// Transform around a center point
around: function (cx, cy, matrix) {
- return this
- .multiply(new SVG.Matrix(1, 0, 0, 1, cx || 0, cy || 0))
- .multiply(matrix)
- .multiply(new SVG.Matrix(1, 0, 0, 1, -cx || 0, -cy || 0))
+ var dx = cx || 0
+ var dy = cy || 0
+ return this.translate(-dx, -dy).lmultiply(matrix).translate(dx, dy)
},
+
// Convert to native SVGMatrix
native: function () {
// create new matrix
@@ -275,6 +237,18 @@ SVG.Matrix = SVG.invent({
return matrix
},
+
+ // Check if two matrices are equal
+ equals: function (other) {
+ var comp = parseMatrix(other)
+ return closeEnough(this.a, comp.a)
+ && closeEnough(this.b, comp.b)
+ && closeEnough(this.c, comp.c)
+ && closeEnough(this.d, comp.d)
+ && closeEnough(this.e, comp.e)
+ && closeEnough(this.f, comp.f)
+ },
+
// Convert matrix to string
toString: function () {
return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')'
diff --git a/src/point.js b/src/point.js
index 682092e..afb972f 100644
--- a/src/point.js
+++ b/src/point.js
@@ -22,13 +22,14 @@ SVG.Point = SVG.invent({
clone: function () {
return new SVG.Point(this)
},
+
// Morph one point into another
morph: function (x, y) {
// store new destination
this.destination = new SVG.Point(x, y)
-
return this
},
+
// Get morphed point at a given position
at: function (pos) {
// make sure a destination is defined
@@ -39,9 +40,9 @@ SVG.Point = SVG.invent({
x: this.x + (this.destination.x - this.x) * pos,
y: this.y + (this.destination.y - this.y) * pos
})
-
return point
},
+
// Convert to native SVGPoint
native: function () {
// create new point
@@ -50,9 +51,9 @@ SVG.Point = SVG.invent({
// update with current values
point.x = this.x
point.y = this.y
-
return point
},
+
// transform point with matrix
transform: function (matrix) {
return new SVG.Point(this.native().matrixTransform(matrix.native()))
@@ -66,5 +67,4 @@ SVG.extend(SVG.Element, {
point: function (x, y) {
return new SVG.Point(x, y).transform(this.screenCTM().inverse())
}
-
})
diff --git a/src/sugar.js b/src/sugar.js
index e82f4bb..54cc289 100644
--- a/src/sugar.js
+++ b/src/sugar.js
@@ -36,43 +36,52 @@ var sugar = {
SVG.extend([SVG.Element, SVG.FX], {
// Map rotation to transform
rotate: function (angle, cx, cy) {
- var matrix = new SVG.Matrix().rotate(angle, cx, cy)
- return this.matrix(matrix, true)
+ return this.transform({rotate: angle, ox: cx, oy: cy}, true)
},
+
// Map skew to transform
skew: function (x, y, cx, cy) {
- var matrix = arguments.length === 1 || arguments.length === 3
- ? new SVG.Matrix().skew(x, x, cx, cy)
- : new SVG.Matrix().skew(x, y, cx, cy)
- return this.matrix(matrix, true)
+ 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)
},
+
// Map scale to transform
scale: function (x, y, cx, cy) {
return arguments.length === 1 || arguments.length === 3
- ? this.transform({ scale: x, cx: y, cy: cx })
- : this.transform({ scaleX: x, scaleY: y, cx: cx, cy: cy })
+ ? this.transform({ scale: x, origin: [y, cx] }, true)
+ : this.transform({ scaleX: x, scaleY: y, origin: [cx, cy] }, true)
},
+
// Map translate to transform
translate: function (x, y) {
- return this.transform({ x: x, y: y })
+ return this.transform({ translate: [x, y] }, true)
},
+
// Map flip to transform
- flip: function (a, o) {
- o = typeof a === 'number' ? a : o
- return this.transform({ flip: a || 'both', offset: o })
+ flip: function (direction, around) {
+ var origin = (direction === "both" && isFinite(around)) ? [around, around]
+ : (direction === "x") ? [around, 0]
+ : (direction === "y") ? [0, around]
+ : undefined
+ this.transform({flip: direction, origin: origin})
},
+
// 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)
diff --git a/src/transform.js b/src/transform.js
index 625a5ab..8801fa2 100644
--- a/src/transform.js
+++ b/src/transform.js
@@ -13,11 +13,16 @@ SVG.extend(SVG.Element, {
.split(SVG.regex.transforms).slice(0, -1).map(function (str) {
// generate key => value pairs
var kv = str.trim().split('(')
- return [kv[0], kv[1].split(SVG.regex.delimiter).map(function (str) { return parseFloat(str) })]
+ return [kv[0],
+ kv[1].split(SVG.regex.delimiter)
+ .map(function (str) { return parseFloat(str) })
+ ]
})
+ .reverse()
// merge every transformation into one matrix
.reduce(function (matrix, transform) {
- if (transform[0] === 'matrix') return matrix.multiply(arrayToMatrix(transform[1]))
+ if (transform[0] === 'matrix')
+ return matrix.lmultiply(arrayToMatrix(transform[1]))
return matrix[transform[0]].apply(matrix, transform[1])
}, new SVG.Matrix())
@@ -44,22 +49,40 @@ SVG.extend(SVG.Element, {
SVG.extend(SVG.Element, {
// Add transformations
- transform: function (o) {
+ transform: function (o, cyOrRel) {
+ // Get the bounding box of the element with no transformations applied
+ var bbox = this.bbox()
+
// Act as a getter if no object was passed
- if (typeof o !== 'object') {
- var matrix = new SVG.Matrix(this).decompose()
- return typeof o === 'string' ? matrix[o] : matrix
- }
+ if (o == null) {
+ return new SVG.Matrix(this)
+
+ // Let the user
+ } 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
- if (typeof o.origin === 'string') {
+ } else if (typeof o.origin === 'string'
+ || (o.origin == null && o.ox == null && o.oy == null)) {
// Get the bounding box and string to use in our calculations
- var string = o.origin.toLowerCase().trim()
- var bbox = this.bbox()
+ var string = typeof o.origin === 'string'
+ ? o.origin.toLowerCase().trim()
+ : 'center' // We want the center by default
+ var height = bbox.height
+ var width = bbox.width
var x = bbox.x
var y = bbox.y
- var width = bbox.width
- var height = bbox.height
// Set the bounds eg : "bottom-left", "Top right", "middle" etc...
o.ox = string.includes('left') ? x
@@ -73,28 +96,13 @@ SVG.extend(SVG.Element, {
o.origin = null
}
- // Get the resulting matrix and apply it to the element
- var result = new SVG.Matrix().form(o)
+ // The user can pass a boolean, an SVG.Element or an SVG.Matrix or nothing
+ var result = new SVG.Matrix(cyOrRel === true ? this : cyOrRel).affine(o)
var matrixString = result.toString()
- // Apply the result
+ // Apply the result directly to this matrix
return this.attr('transform', matrixString)
},
-
- // Map matrix to transform
- matrix: function (m, relative) {
- // Construct a matrix from the first parameter
- var matrix = new SVG.Matrix(m)
-
- // If we have a relative matrix, we just apply the old matrix
- if (relative) {
- var oldMatrix = new SVG.Matrix(this)
- matrix = oldMatrix.multiply(matrix)
- }
-
- // Apply the matrix directly
- return this.attr('transform', matrix)
- }
})
SVG.extend(SVG.FX, {