]> source.dussan.org Git - svg.js.git/commitdiff
Implemented new transformations
authorSaivan <savian@me.com>
Fri, 2 Mar 2018 01:14:42 +0000 (12:14 +1100)
committerSaivan <savian@me.com>
Fri, 2 Mar 2018 01:14:42 +0000 (12:14 +1100)
This commit implements the new transformation model, but it also
needs to modify a few tests to fit the new format. This is still
a work in progress.

17 files changed:
CHANGELOG.md
README.md
dist/svg.js
dist/svg.min.js
playgrounds/transforms/transforms.html
playgrounds/transforms/transforms.js
spec/SpecRunner.html
spec/spec/element.js
spec/spec/helper.js
spec/spec/matrix.js
src/boxes.js
src/helpers.js
src/line.js
src/matrix.js
src/point.js
src/sugar.js
src/transform.js

index ebbc67891802e3049b238722de186924abba5b96..e0ee5cb0b4eae6e82cb4fbec5358b867fc5b8c4d 100644 (file)
@@ -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!__
index d0d7fdf1828363fcf883e2ac8f83b70b8fbd281d..ce9c65e5415206c3cb89f84a501a0e947d31a0ae 100644 (file)
--- 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:
index 98156739ea8e667d7297b6ad090418097d98965b..77f87217b0daf185260acc93e83284d9d03bd720 100644 (file)
@@ -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
index 2d6360d1b9512ddf173f499d47ed5500053873d3..30171f0c2e935f7510992c41253c01118d92cc38 100644 (file)
@@ -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
index 4382745b8fe456376e0a58b4af5511c799940a99..58eb5dcc0e929267f6a1b9f397793108f7a25e87 100644 (file)
 
     <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>
index 797fa657da61dbc88762691e796cea9504a8e800..3b12f65d321b3fb4dd164b0d9a200ae11c03787d 100644 (file)
@@ -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')
index 7461bdd3655c46132cdb7ccffce6aae5b73d56cd..1ecef128ae459ddc93f5b7338f8224eb46db6dbc 100644 (file)
@@ -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>
   <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>
index a5b26a113e08aa293a23b6963f609e9fe5488299..3f62e5a0c6ce74e751a54c6b9a98c00d706310a8 100644 (file)
@@ -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() {
index 3dd6aff9a70334e00f73086a23ca906fb7d159c5..4c15acda222da928631324ef4f019eae7017cd3f 100644 (file)
@@ -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)
index 0816f6637ab7bf638b3892f115d741a0265b0dd4..08e0280ac81b2bc49a1d9da633f88d92d8620663 100644 (file)
@@ -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)
     })
   })
 
index a5ca1e8b9d0cc574f91de68892c4a78da21098dd..cd90207e9222668353ed0db8a79dd29b9ab390ee 100644 (file)
@@ -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
index 56565a04d84632496a2a70643f11ddadbfc66fb0..16e6e4ea29a70bda133ace5bf076a82d50467441 100644 (file)
@@ -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)
 }
index 100d625d0a3fcd317189f6bcfc5b1d60b735c124..da0c0cad01f1b415bf691d7b11994f8dd8722559 100644 (file)
@@ -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)
index a7676da1d73fdda28a1105409b8012af10a846f9..970f6eda650bf47681125a862f7b9b191f2121f2 100644 (file)
@@ -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 + ')'
index 682092e53835a9dc955d4ba7bab3b014e9325e05..afb972f683e34bfb667e7beca5c6aef528263379 100644 (file)
@@ -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())
   }
-
 })
index e82f4bbb436ceec70ac66228a614326bc4a502e5..54cc28943d4dfd61faba11f5a1fb022004b35868 100644 (file)
@@ -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)
index 625a5abff1e45021194e0fd8b3400bb189c201d2..8801fa2eca1550511ac43b812a884e975219d3c0 100644 (file)
@@ -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, {