From 9bfcbc184ec99631ea7d2b912e79b1edde17a111 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ulrich-Matthias=20Sch=C3=A4fer?= Date: Thu, 16 Mar 2017 12:48:20 +0100 Subject: [PATCH] unified all boxes (#634) unified all boxes - SVG.Box for everything - bbox, rbox and viewbox as methods - boxes can be created with string, array, object, list... - added helper to simplify boxes code --- bench/runner.html | 1 + bench/tests/10000-boxes.js | 55 +++++ dist/svg.js | 463 +++++++++++++------------------------ dist/svg.min.js | 4 +- gulpfile.js | 3 +- spec/SpecRunner.html | 1 - spec/spec/boxes.js | 239 +++++++++++-------- spec/spec/element.js | 4 +- spec/spec/set.js | 6 +- spec/spec/viewbox.js | 162 ------------- src/boxes.js | 201 +++++++--------- src/fx.js | 2 +- src/helpers.js | 16 +- src/set.js | 8 +- src/viewbox.js | 127 ---------- 15 files changed, 471 insertions(+), 821 deletions(-) create mode 100644 bench/tests/10000-boxes.js delete mode 100644 spec/spec/viewbox.js delete mode 100644 src/viewbox.js diff --git a/bench/runner.html b/bench/runner.html index 31b97c1..a0bc5d9 100644 --- a/bench/runner.html +++ b/bench/runner.html @@ -43,6 +43,7 @@ + diff --git a/bench/tests/10000-boxes.js b/bench/tests/10000-boxes.js new file mode 100644 index 0000000..0466f64 --- /dev/null +++ b/bench/tests/10000-boxes.js @@ -0,0 +1,55 @@ +SVG.bench.describe('Generate 100000 bbox', function(bench) { + var rect = bench.draw.rect(100,100) + + bench.test('using SVG.js v3.0.0', function() { + for (var i = 0; i < 100000; i++) + rect.bbox() + }) + //bench.test('using vanilla js', function() { + // var node = rect.node + // for (var i = 0; i < 10000; i++) { + // node.getBBox() + // } + //}) + //bench.test('using Snap.svg v0.5.1', function() { + // for (var i = 0; i < 10000; i++) + // bench.snap.rect(50, 50, 100, 100) + //}) +}) + +SVG.bench.describe('Generate 100000 rbox', function(bench) { + var rect = bench.draw.rect(100,100) + + bench.test('using SVG.js v3.0.0', function() { + for (var i = 0; i < 100000; i++) + rect.bbox() + }) + //bench.test('using vanilla js', function() { + // var node = rect.node + // for (var i = 0; i < 10000; i++) { + // node.getBoundingClientRect() + // } + //}) + //bench.test('using Snap.svg v0.5.1', function() { + // for (var i = 0; i < 10000; i++) + // bench.snap.rect(50, 50, 100, 100) + //}) +}) +SVG.bench.describe('Generate 100000 viewbox', function(bench) { + var nested = bench.draw.nested().viewbox(10, 10, 100, 100) + + bench.test('using SVG.js v3.0.0', function() { + for (var i = 0; i < 100000; i++) + nested.viewbox() + }) + //bench.test('using vanilla js', function() { + // var node = rect.node + // for (var i = 0; i < 10000; i++) { + // node.getAttribute('viewBox') + // } + //}) + //bench.test('using Snap.svg v0.5.1', function() { + // for (var i = 0; i < 10000; i++) + // bench.snap.rect(50, 50, 100, 100) + //}) +}) diff --git a/dist/svg.js b/dist/svg.js index 0a461ec..e22ff37 100644 --- a/dist/svg.js +++ b/dist/svg.js @@ -6,7 +6,7 @@ * @copyright Wout Fierens * @license MIT * -* BUILT: Fri Mar 10 2017 14:56:03 GMT+0100 (Mitteleuropäische Zeit) +* BUILT: Wed Mar 15 2017 11:41:47 GMT+0100 (Mitteleuropäische Zeit) */; (function(root, factory) { if (typeof define === 'function' && define.amd) { @@ -2132,7 +2132,7 @@ SVG.extend(SVG.FX, { // Add animatable viewbox , viewbox: function(x, y, width, height) { if (this.target() instanceof SVG.Container) { - this.add('viewbox', new SVG.ViewBox(x, y, width, height)) + this.add('viewbox', new SVG.Box(x, y, width, height)) } return this @@ -2156,176 +2156,6 @@ SVG.extend(SVG.FX, { } }) -SVG.Box = SVG.invent({ - create: function(x, y, width, height) { - if (typeof x == 'object' && !(x instanceof SVG.Element)) { - // chromes getBoundingClientRect has no x and y property - return SVG.Box.call(this, x.left != null ? x.left : x.x , x.top != null ? x.top : x.y, x.width, x.height) - } else if (arguments.length == 4) { - this.x = x - this.y = y - this.width = width - this.height = height - - } - - // add center, right, bottom... - fullBox(this) - } -, extend: { - // Merge rect box with another, return a new instance - merge: function(box) { - var b = new this.constructor() - - // merge boxes - b.x = Math.min(this.x, box.x) - b.y = Math.min(this.y, box.y) - b.width = Math.max(this.x + this.width, box.x + box.width) - b.x - b.height = Math.max(this.y + this.height, box.y + box.height) - b.y - - return fullBox(b) - } - - , transform: function(m) { - var xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, p - - var pts = [ - new SVG.Point(this.x, this.y), - new SVG.Point(this.x2, this.y), - new SVG.Point(this.x, this.y2), - new SVG.Point(this.x2, this.y2) - ] - - pts.forEach(function(p) { - p = p.transform(m) - xMin = Math.min(xMin,p.x) - xMax = Math.max(xMax,p.x) - yMin = Math.min(yMin,p.y) - yMax = Math.max(yMax,p.y) - }) - - bbox = new this.constructor() - bbox.x = xMin - bbox.width = xMax-xMin - bbox.y = yMin - bbox.height = yMax-yMin - - fullBox(bbox) - - return bbox - } - } -}) - -SVG.BBox = SVG.invent({ - // Initialize - create: function(element) { - SVG.Box.apply(this, [].slice.call(arguments)) - - // get values if element is given - if (element instanceof SVG.Element) { - var box - - // yes this is ugly, but Firefox can be a bitch when it comes to elements that are not yet rendered - try { - - if (!document.documentElement.contains){ - // This is IE - it does not support contains() for top-level SVGs - var topParent = element.node; - while (topParent.parentNode){ - topParent = topParent.parentNode; - } - if (topParent != document) throw new Exception('Element not in the dom') - } else { - // the element is NOT in the dom, throw error - if(!document.documentElement.contains(element.node)) throw new Exception('Element not in the dom') - } - - // find native bbox - box = element.node.getBBox() - } catch(e) { - if(element instanceof SVG.Shape){ - var clone = element.clone(SVG.parser.draw).show() - box = clone.bbox() - clone.remove() - }else{ - box = { - x: element.node.clientLeft - , y: element.node.clientTop - , width: element.node.clientWidth - , height: element.node.clientHeight - } - } - } - - SVG.Box.call(this, box) - } - - } - - // Define ancestor -, inherit: SVG.Box - - // Define Parent -, parent: SVG.Element - - // Constructor -, construct: { - // Get bounding box - bbox: function() { - return new SVG.BBox(this) - } - } - -}) - -SVG.BBox.prototype.constructor = SVG.BBox - - -SVG.extend(SVG.Element, { - tbox: function(){ - console.warn('Use of TBox is deprecated and mapped to RBox. Use .rbox() instead.') - return this.rbox(this.doc()) - } -}) - -SVG.RBox = SVG.invent({ - // Initialize - create: function(element) { - SVG.Box.apply(this, [].slice.call(arguments)) - - if (element instanceof SVG.Element) { - SVG.Box.call(this, element.node.getBoundingClientRect()) - } - } - -, inherit: SVG.Box - - // define Parent -, parent: SVG.Element - -, extend: { - addOffset: function() { - // offset by window scroll position, because getBoundingClientRect changes when window is scrolled - this.x += window.pageXOffset - this.y += window.pageYOffset - return this - } - } - - // Constructor -, construct: { - // Get rect box - rbox: function(el) { - if (el) return new SVG.RBox(this).transform(el.screenCTM().inverse()) - return new SVG.RBox(this).addOffset() - } - } - -}) - -SVG.RBox.prototype.constructor = SVG.RBox - SVG.Matrix = SVG.invent({ // Initialize create: function(source) { @@ -3177,133 +3007,6 @@ SVG.Container = SVG.invent({ // Inherit from , inherit: SVG.Parent -}) - -SVG.ViewBox = SVG.invent({ - - create: function(source) { - var i, base = [0, 0, 0, 0] - - var x, y, width, height, box, view, we, he - , wm = 1 // width multiplier - , hm = 1 // height multiplier - , reg = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/gi - - if(source instanceof SVG.Element){ - - we = source - he = source - view = (source.attr('viewBox') || '').match(reg) - box = source.bbox - - // get dimensions of current node - width = new SVG.Number(source.width()) - height = new SVG.Number(source.height()) - - // find nearest non-percentual dimensions - while (width.unit == '%') { - wm *= width.value - width = new SVG.Number(we instanceof SVG.Doc ? we.parent().offsetWidth : we.parent().width()) - we = we.parent() - } - while (height.unit == '%') { - hm *= height.value - height = new SVG.Number(he instanceof SVG.Doc ? he.parent().offsetHeight : he.parent().height()) - he = he.parent() - } - - // ensure defaults - this.x = 0 - this.y = 0 - this.width = width * wm - this.height = height * hm - this.zoom = 1 - - if (view) { - // get width and height from viewbox - x = parseFloat(view[0]) - y = parseFloat(view[1]) - width = parseFloat(view[2]) - height = parseFloat(view[3]) - - // calculate zoom accoring to viewbox - this.zoom = ((this.width / this.height) > (width / height)) ? - this.height / height : - this.width / width - - // calculate real pixel dimensions on parent SVG.Doc element - this.x = x - this.y = y - this.width = width - this.height = height - - } - - }else{ - - // ensure source as object - source = typeof source === 'string' ? - source.match(reg).map(function(el){ return parseFloat(el) }) : - Array.isArray(source) ? - source : - typeof source == 'object' ? - [source.x, source.y, source.width, source.height] : - arguments.length == 4 ? - [].slice.call(arguments) : - base - - this.x = source[0] - this.y = source[1] - this.width = source[2] - this.height = source[3] - } - - - } - -, extend: { - - toString: function() { - return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height - } - , morph: function(x, y, width, height){ - this.destination = new SVG.ViewBox(x, y, width, height) - return this - } - - , at: function(pos) { - - if(!this.destination) return this - - return new SVG.ViewBox([ - 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 -, parent: SVG.Container - - // Add parent method -, construct: { - - // get/set viewbox - viewbox: function(x, y, width, height) { - if (arguments.length == 0) - // act as a getter if there are no arguments - return new SVG.ViewBox(this) - - // otherwise act as a setter - return this.attr('viewBox', new SVG.ViewBox(x, y, width, height)) - } - - } - }) // Add events to elements ;[ 'click' @@ -5062,17 +4765,17 @@ SVG.Set = SVG.invent({ , bbox: function(){ // return an empty box of there are no members if (this.members.length == 0) - return new SVG.RBox() + return new SVG.Box() // get the first rbox and update the target bbox - var rbox = this.members[0].rbox(this.members[0].doc()) + var box = this.members[0].rbox(this.members[0].doc()) this.each(function() { // user rbox for correct position and visual representation - rbox = rbox.merge(this.rbox(this.doc())) + box = box.merge(this.rbox(this.doc())) }) - return rbox + return box } } @@ -5233,6 +4936,20 @@ SVG.extend(SVG.Parent, { } }) +function isNulledBox(box) { + return !box.w && !box.h && !box.x && !box.y +} + +function domContains(node) { + return (document.documentElement.contains || function(node) { + // This is IE - it does not support contains() for top-level SVGs + while (node.parentNode){ + node = node.parentNode; + } + return node == document + }).call(document.documentElement, node) +} + function pathRegReplace(a, b, c, d) { return c + d.replace(SVG.regex.dots, ' .') } @@ -5422,6 +5139,146 @@ function idFromReference(url) { // Create matrix array for looping var abcdef = 'abcdef'.split('') +SVG.Box = SVG.invent({ + create: function(source) { + var base = [0,0,0,0] + source = typeof source === 'string' ? + source.split(SVG.regex.delimiter).map(parseFloat) : + Array.isArray(source) ? + source : + typeof source == 'object' ? + [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] : + arguments.length == 4 ? + [].slice.call(arguments) : + base + + this.x = source[0] + this.y = source[1] + this.width = source[2] + this.height = source[3] + + // add center, right, bottom... + fullBox(this) + } +, extend: { + // Merge rect box with another, return a new instance + merge: function(box) { + var x = Math.min(this.x, box.x) + , y = Math.min(this.y, box.y) + + return new SVG.Box( + x, y, + Math.max(this.x + this.width, box.x + box.width) - x, + Math.max(this.y + this.height, box.y + box.height) - y + ) + } + + , transform: function(m) { + var xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, p + + var pts = [ + new SVG.Point(this.x, this.y), + new SVG.Point(this.x2, this.y), + new SVG.Point(this.x, this.y2), + new SVG.Point(this.x2, this.y2) + ] + + pts.forEach(function(p) { + p = p.transform(m) + xMin = Math.min(xMin,p.x) + xMax = Math.max(xMax,p.x) + yMin = Math.min(yMin,p.y) + yMax = Math.max(yMax,p.y) + }) + + return new SVG.Box( + xMin, yMin, + xMax-xMin, + yMax-yMin + ) + } + + , addOffset: function() { + // offset by window scroll position, because getBoundingClientRect changes when window is scrolled + this.x += window.pageXOffset + 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 + } + + , at: function(pos) { + + 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 + ) + + } + } + + // Define Parent +, parent: SVG.Element + + // Constructor +, construct: { + // Get bounding box + bbox: function() { + var box + + try { + // find native bbox + box = this.node.getBBox() + + if(isNulledBox(box) && !domContains(this.node)) { + throw new Exception('Element not in the dom') + } + } catch(e) { + try { + var clone = this.clone(SVG.parser.draw).show() + box = clone.node.getBBox() + clone.remove() + } catch(e) { + console.warn('Getting a bounding box of this element is not possible') + } + } + + return new SVG.Box(box) + } + + , rbox: function(el) { + // IE11 throws an error when element not in dom + try{ + var box = new SVG.Box(this.node.getBoundingClientRect()) + if (el) return box.transform(el.screenCTM().inverse()) + return box.addOffset() + } catch(e) { + return new SVG.Box() + } + } + } +}) + +SVG.extend(SVG.Doc, SVG.Nested, SVG.Symbol, SVG.Image, SVG.Pattern, SVG.Marker, SVG.ForeignObject, SVG.View, { + viewbox: function(x, y, width, height) { + // act as getter + if(x == null) return new SVG.Box(this.attr('viewBox')) + + // act as setter + return this.attr('viewBox', new SVG.Box(x, y, width, height)) + } +}) + + return SVG })); \ No newline at end of file diff --git a/dist/svg.min.js b/dist/svg.min.js index 527bd4f..7a6d14f 100644 --- a/dist/svg.min.js +++ b/dist/svg.min.js @@ -1,2 +1,2 @@ -/*! svg.js v2.5.0 MIT*/;!function(t,e){"function"==typeof define&&define.amd?define(function(){return e(t,t.document)}):"object"==typeof exports?module.exports=t.document?e(t,t.document):function(t){return e(t,t.document)}:t.SVG=e(t,t.document)}("undefined"!=typeof window?window:this,function(t,e){function i(t,e,i,n){return i+n.replace(w.regex.dots," .")}function n(t){for(var e=t.slice(0),i=e.length;i--;)Array.isArray(e[i])&&(e[i]=n(e[i]));return e}function r(t,e){return t instanceof e}function s(t,e){return(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)}function o(t){return t.toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()})}function a(t){return t.charAt(0).toUpperCase()+t.slice(1)}function h(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 u(t){var e=t.toString(16);return 1==e.length?"0"+e:e}function l(t,e,i){if(null==e||null==i){var n=t.bbox();null==e?e=n.width/n.height*i:null==i&&(i=n.height/n.width*e)}return{width:e,height:i}}function c(t,e,i){return{x:e*t.a+i*t.c+0,y:e*t.b+i*t.d+0}}function f(t){return{a:t[0],b:t[1],c:t[2],d:t[3],e:t[4],f:t[5]}}function d(t){return t instanceof w.Matrix||(t=new w.Matrix(t)),t}function p(t,e){t.cx=null==t.cx?e.bbox().cx:t.cx,t.cy=null==t.cy?e.bbox().cy:t.cy}function m(t){return t=t.replace(w.regex.whitespace,"").replace(w.regex.matrix,"").split(w.regex.matrixElements),f(w.utils.map(t,function(t){return parseFloat(t)}))}function x(t){for(var e=0,i=t.length,n="";e=0;e--)t.childNodes[e]instanceof SVGElement&&y(t.childNodes[e]);return w.adopt(t).id(w.eid(t.nodeName))}function v(t){return null==t.x&&(t.x=0,t.y=0,t.width=0,t.height=0),t.w=t.width,t.h=t.height,t.x2=t.x+t.width,t.y2=t.y+t.height,t.cx=t.x+t.width/2,t.cy=t.y+t.height/2,t}function g(t){var e=(t||"").toString().match(w.regex.reference);if(e)return e[1]}var w=this.SVG=function(t){if(w.supported)return t=new w.Doc(t),w.parser.draw||w.prepare(),t};if(w.ns="http://www.w3.org/2000/svg",w.xmlns="http://www.w3.org/2000/xmlns/",w.xlink="http://www.w3.org/1999/xlink",w.svgjs="http://svgjs.com/svgjs",w.supported=function(){return!!e.createElementNS&&!!e.createElementNS(w.ns,"svg").createSVGRect}(),!w.supported)return!1;w.did=1e3,w.eid=function(t){return"Svgjs"+a(t)+w.did++},w.create=function(t){var i=e.createElementNS(this.ns,t);return i.setAttribute("id",this.eid(t)),i},w.extend=function(){var t,e,i,n;for(t=[].slice.call(arguments),e=t.pop(),n=t.length-1;n>=0;n--)if(t[n])for(i in e)t[n].prototype[i]=e[i];w.Set&&w.Set.inherit&&w.Set.inherit()},w.invent=function(t){var e="function"==typeof t.create?t.create:function(){this.constructor.call(this,w.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&w.extend(e,t.extend),t.construct&&w.extend(t.parent||w.Container,t.construct),e},w.adopt=function(t){if(!t)return null;if(t.instance)return t.instance;var e;return e="svg"==t.nodeName?t.parentNode instanceof SVGElement?new w.Nested:new w.Doc:"linearGradient"==t.nodeName?new w.Gradient("linear"):"radialGradient"==t.nodeName?new w.Gradient("radial"):w[a(t.nodeName)]?new(w[a(t.nodeName)]):new w.Element(t),e.type=t.nodeName,e.node=t,t.instance=e,e instanceof w.Doc&&e.namespace().defs(),e.setData(JSON.parse(t.getAttribute("svgjs:data"))||{}),e},w.prepare=function(){var t=e.getElementsByTagName("body")[0],i=(t?new w.Doc(t):new w.Doc(e.documentElement).nested()).size(2,0);w.parser={body:t||e.documentElement,draw:i.style("opacity:0;position:absolute;left:-100%;top:-100%;overflow:hidden"),poly:i.polyline().node,path:i.path().node,native:w.create("svg")}},w.parser={native:w.create("svg")},e.addEventListener("DOMContentLoaded",function(){w.parser.draw||w.prepare()},!1),w.regex={numberAndUnit:/^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+)\)/,reference:/#([a-z0-9\-_]+)/i,matrix:/matrix\(|\)/g,matrixElements:/,*\s+|,/,whitespace:/\s/g,isHex:/^#[a-f0-9]{3,6}$/i,isRgb:/^rgb\(/,isCss:/[^:]+:[^;]+;?/,isBlank:/^(\s+)?$/,isNumber:/^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,isPercent:/^-?[\d\.]+%$/,isImage:/\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,delimiter:/[\s,]+/,hyphen:/([^e])\-/gi,pathLetters:/[MLHVCSQTAZ]/gi,isPathLetter:/[MLHVCSQTAZ]/i,numbersWithDots:/((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi,dots:/\./g},w.utils={map:function(t,e){var i,n=t.length,r=[];for(i=0;i1?1:t,new w.Color({r:~~(this.r+(this.destination.r-this.r)*t),g:~~(this.g+(this.destination.g-this.g)*t),b:~~(this.b+(this.destination.b-this.b)*t)})):this}}),w.Color.test=function(t){return t+="",w.regex.isHex.test(t)||w.regex.isRgb.test(t)},w.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},w.Color.isColor=function(t){return w.Color.isRgb(t)||w.Color.test(t)},w.Array=function(t,e){t=(t||[]).valueOf(),0==t.length&&e&&(t=e.valueOf()),this.value=this.parse(t)},w.extend(w.Array,{morph:function(t){if(this.destination=this.parse(t),this.value.length!=this.destination.length){for(var e=this.value[this.value.length-1],i=this.destination[this.destination.length-1];this.value.length>this.destination.length;)this.destination.push(i);for(;this.value.length=0;n--)this.value[n]=[this.value[n][0]+t,this.value[n][1]+e];return this},size:function(t,e){var i,n=this.bbox();for(i=this.value.length-1;i>=0;i--)n.width&&(this.value[i][0]=(this.value[i][0]-n.x)*t/n.width+n.x),n.height&&(this.value[i][1]=(this.value[i][1]-n.y)*e/n.height+n.y);return this},bbox:function(){return w.parser.poly.setAttribute("points",this.toString()),w.parser.poly.getBBox()}}),w.PathArray=function(t,e){w.Array.call(this,t,e||[["M",0,0]])},w.PathArray.prototype=new w.Array,w.PathArray.prototype.constructor=w.PathArray,w.extend(w.PathArray,{toString:function(){return x(this.value)},move:function(t,e){var i=this.bbox();if(t-=i.x,e-=i.y,!isNaN(t)&&!isNaN(e))for(var n,r=this.value.length-1;r>=0;r--)n=this.value[r][0],"M"==n||"L"==n||"T"==n?(this.value[r][1]+=t,this.value[r][2]+=e):"H"==n?this.value[r][1]+=t:"V"==n?this.value[r][1]+=e:"C"==n||"S"==n||"Q"==n?(this.value[r][1]+=t,this.value[r][2]+=e,this.value[r][3]+=t,this.value[r][4]+=e,"C"==n&&(this.value[r][5]+=t,this.value[r][6]+=e)):"A"==n&&(this.value[r][6]+=t,this.value[r][7]+=e);return this},size:function(t,e){var i,n,r=this.bbox();for(i=this.value.length-1;i>=0;i--)n=this.value[i][0],"M"==n||"L"==n||"T"==n?(this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x,this.value[i][2]=(this.value[i][2]-r.y)*e/r.height+r.y):"H"==n?this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x:"V"==n?this.value[i][1]=(this.value[i][1]-r.y)*e/r.height+r.y:"C"==n||"S"==n||"Q"==n?(this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x,this.value[i][2]=(this.value[i][2]-r.y)*e/r.height+r.y,this.value[i][3]=(this.value[i][3]-r.x)*t/r.width+r.x,this.value[i][4]=(this.value[i][4]-r.y)*e/r.height+r.y,"C"==n&&(this.value[i][5]=(this.value[i][5]-r.x)*t/r.width+r.x,this.value[i][6]=(this.value[i][6]-r.y)*e/r.height+r.y)):"A"==n&&(this.value[i][1]=this.value[i][1]*t/r.width,this.value[i][2]=this.value[i][2]*e/r.height,this.value[i][6]=(this.value[i][6]-r.x)*t/r.width+r.x,this.value[i][7]=(this.value[i][7]-r.y)*e/r.height+r.y);return this},equalCommands:function(t){var e,i,n;for(t=new w.PathArray(t),n=this.value.length===t.value.length,e=0,i=this.value.length;n&&ei.x&&e>i.y&&t/,"").replace(/<\/svg>$/,"");i.innerHTML=""+t.replace(/\n/,"").replace(/<(\w+)([^<]+?)\/>/g,"<$1$2>")+"";for(var n=0,r=i.firstChild.childNodes.length;n":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return-Math.cos(t*Math.PI/2)+1}},w.morph=function(t){return function(e,i){return new w.MorphObj(e,i).at(t)}},w.Situation=w.invent({create:function(t){this.init=!1,this.reversed=!1,this.reversing=!1,this.duration=new w.Number(t.duration).valueOf(),this.delay=new w.Number(t.delay).valueOf(),this.start=+new Date+this.delay,this.finish=this.start+this.duration,this.ease=t.ease,this.loop=0,this.loops=!1,this.animations={},this.attrs={},this.styles={},this.transforms=[],this.once={}}}),w.FX=w.invent({create:function(t){this._target=t,this.situations=[],this.active=!1,this.situation=null,this.paused=!1,this.lastPos=0,this.pos=0,this.absPos=0,this._speed=1},extend:{animate:function(t,e,i){"object"==typeof t&&(e=t.ease,i=t.delay,t=t.duration);var n=new w.Situation({duration:t||1e3,delay:i||0,ease:w.easing[e||"-"]||e});return this.queue(n),this},delay:function(t){var e=new w.Situation({duration:t,delay:0,ease:w.easing["-"]});return this.queue(e)},target:function(t){return t&&t instanceof w.Element?(this._target=t,this):this._target},timeToAbsPos:function(t){return(t-this.situation.start)/(this.situation.duration/this._speed)},absPosToTime:function(t){return this.situation.duration/this._speed*t+this.situation.start},startAnimFrame:function(){this.stopAnimFrame(),this.animationFrame=requestAnimationFrame(function(){this.step()}.bind(this))},stopAnimFrame:function(){cancelAnimationFrame(this.animationFrame)},start:function(){return!this.active&&this.situation&&(this.active=!0,this.startCurrent()),this},startCurrent:function(){return this.situation.start=+new Date+this.situation.delay/this._speed,this.situation.finish=this.situation.start+this.situation.duration/this._speed,this.initAnimations().step()},queue:function(t){return("function"==typeof t||t instanceof w.Situation)&&this.situations.push(t),this.situation||(this.situation=this.situations.shift()),this},dequeue:function(){return this.stop(),this.situation=this.situations.shift(),this.situation&&(this.situation instanceof w.Situation?this.start():this.situation.call(this)),this},initAnimations:function(){var t,e,i=this.situation;if(i.init)return this;for(t in i.animations)e=this.target()[t](),i.animations[t]instanceof w.Number&&(e=new w.Number(e)),i.animations[t]=e.morph(i.animations[t]);for(t in i.attrs)i.attrs[t]=new w.MorphObj(this.target().attr(t),i.attrs[t]);for(t in i.styles)i.styles[t]=new w.MorphObj(this.target().style(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 i=this.active;return this.active=!1,e&&this.clearQueue(),t&&this.situation&&(!i&&this.startCurrent(),this.atEnd()),this.stopAnimFrame(),this.clearCurrent()},reset:function(){if(this.situation){var t=this.situation;this.stop(),this.situation=t,this.atStart()}return this},finish:function(){for(this.stop(!0,!1);this.dequeue().situation&&this.stop(!0,!1););return this.clearQueue().clearCurrent(),this},atStart:function(){return this.at(0,!0)},atEnd:function(){return this.situation.loops===!0&&(this.situation.loops=this.situation.loop+1),"number"==typeof this.situation.loops?this.at(this.situation.loops,!0):this.at(1,!0)},at:function(t,e){var i=this.situation.duration/this._speed;return this.absPos=t,e||(this.situation.reversed&&(this.absPos=1-this.absPos),this.absPos+=this.situation.loop),this.situation.start=+new Date-this.absPos*i,this.situation.finish=this.situation.start+i,this.step(!0)},speed:function(t){return 0===t?this.pause():t?(this._speed=t,this.at(this.absPos,!0)):this._speed},loop:function(t,e){var i=this.last();return i.loops=null==t||t,i.loop=0,e&&(i.reversing=!0),this},pause:function(){return this.paused=!0,this.stopAnimFrame(),this},play:function(){return this.paused?(this.paused=!1,this.at(this.absPos,!0)):this},reverse:function(t){var e=this.last();return"undefined"==typeof t?e.reversed=!e.reversed:e.reversed=t,this},progress:function(t){return t?this.situation.ease(this.pos):this.pos},after:function(t){var e=this.last(),i=function i(n){n.detail.situation==e&&(t.call(this,e),this.off("finished.fx",i))};return this.target().on("finished.fx",i),this._callStart()},during:function(t){var e=this.last(),i=function(i){i.detail.situation==e&&t.call(this,i.detail.pos,w.morph(i.detail.pos),i.detail.eased,e)};return this.target().off("during.fx",i).on("during.fx",i),this.after(function(){this.off("during.fx",i)}),this._callStart()},afterAll:function(t){var e=function e(i){t.call(this),this.off("allfinished.fx",e)};return this.target().off("allfinished.fx",e).on("allfinished.fx",e),this._callStart()},duringAll:function(t){var e=function(e){t.call(this,e.detail.pos,w.morph(e.detail.pos),e.detail.eased,e.detail.situation)};return this.target().off("during.fx",e).on("during.fx",e),this.afterAll(function(){this.off("during.fx",e)}),this._callStart()},last:function(){return this.situations.length?this.situations[this.situations.length-1]:this.situation},add:function(t,e,i){return this.last()[i||"animations"][t]=e,this._callStart()},step:function(t){if(t||(this.absPos=this.timeToAbsPos(+new Date)),this.situation.loops!==!1){var e,i,n;e=Math.max(this.absPos,0),i=Math.floor(e),this.situation.loops===!0||ithis.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.target().off(".fx"),this.active=!1),this.active?this.dequeue():this.clearCurrent()):!this.paused&&this.active&&this.startAnimFrame(),this.lastPos=r,this):this},eachAt:function(){var t,e,i=this,n=this.target(),r=this.situation;for(t in r.animations)e=[].concat(r.animations[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(i.pos),i.pos):t}),n[t].apply(n,e);for(t in r.attrs)e=[t].concat(r.attrs[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(i.pos),i.pos):t}),n.attr.apply(n,e);for(t in r.styles)e=[t].concat(r.styles[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(i.pos),i.pos):t}),n.style.apply(n,e);if(r.transforms.length){for(e=r.initialTransformation,t=0,len=r.transforms.length;t1?[].slice.call(arguments):arguments[0])},leading:function(t){return this.target().leading?this.add("leading",new w.Number(t)):this},viewbox:function(t,e,i,n){return this.target()instanceof w.Container&&this.add("viewbox",new w.ViewBox(t,e,i,n)),this},update:function(t){if(this.target()instanceof w.Stop){if("number"==typeof t||t instanceof w.Number)return this.update({offset:arguments[0],color:arguments[1],opacity:arguments[2]});null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",t.offset)}return this}}),w.Box=w.invent({create:function(t,e,i,n){return"object"!=typeof t||t instanceof w.Element?(4==arguments.length&&(this.x=t,this.y=e,this.width=i,this.height=n),void v(this)):w.Box.call(this,null!=t.left?t.left:t.x,null!=t.top?t.top:t.y,t.width,t.height)},extend:{merge:function(t){var e=new this.constructor;return e.x=Math.min(this.x,t.x),e.y=Math.min(this.y,t.y),e.width=Math.max(this.x+this.width,t.x+t.width)-e.x,e.height=Math.max(this.y+this.height,t.y+t.height)-e.y,v(e)},transform:function(t){var e=1/0,i=-(1/0),n=1/0,r=-(1/0),s=[new w.Point(this.x,this.y),new w.Point(this.x2,this.y),new w.Point(this.x,this.y2),new w.Point(this.x2,this.y2)];return s.forEach(function(s){s=s.transform(t),e=Math.min(e,s.x),i=Math.max(i,s.x),n=Math.min(n,s.y),r=Math.max(r,s.y)}),bbox=new this.constructor,bbox.x=e,bbox.width=i-e,bbox.y=n,bbox.height=r-n,v(bbox),bbox}}}),w.BBox=w.invent({create:function(t){if(w.Box.apply(this,[].slice.call(arguments)),t instanceof w.Element){var i;try{if(e.documentElement.contains){if(!e.documentElement.contains(t.node))throw new Exception("Element not in the dom")}else{for(var n=t.node;n.parentNode;)n=n.parentNode;if(n!=e)throw new Exception("Element not in the dom")}i=t.node.getBBox()}catch(e){if(t instanceof w.Shape){var r=t.clone(w.parser.draw).show();i=r.bbox(),r.remove()}else i={x:t.node.clientLeft,y:t.node.clientTop,width:t.node.clientWidth,height:t.node.clientHeight}}w.Box.call(this,i)}},inherit:w.Box,parent:w.Element,construct:{bbox:function(){return new w.BBox(this)}}}),w.BBox.prototype.constructor=w.BBox,w.extend(w.Element,{tbox:function(){return console.warn("Use of TBox is deprecated and mapped to RBox. Use .rbox() instead."),this.rbox(this.doc())}}),w.RBox=w.invent({create:function(t){w.Box.apply(this,[].slice.call(arguments)),t instanceof w.Element&&w.Box.call(this,t.node.getBoundingClientRect())},inherit:w.Box,parent:w.Element,extend:{addOffset:function(){return this.x+=t.pageXOffset,this.y+=t.pageYOffset,this}},construct:{rbox:function(t){return t?new w.RBox(this).transform(t.screenCTM().inverse()):new w.RBox(this).addOffset()}}}),w.RBox.prototype.constructor=w.RBox,w.Matrix=w.invent({create:function(t){var e,i=f([1,0,0,1,0,0]);for(t=t instanceof w.Element?t.matrixify():"string"==typeof t?m(t):6==arguments.length?f([].slice.call(arguments)):Array.isArray(t)?f(t):"object"==typeof t?t:i,e=C.length-1;e>=0;--e)this[C[e]]=t&&"number"==typeof t[C[e]]?t[C[e]]:i[C[e]]},extend:{extract:function(){var t=c(this,0,1),e=c(this,1,0),i=180/Math.PI*Math.atan2(t.y,t.x)-90;return{x:this.e,y:this.f,transformedX:(this.e*Math.cos(i*Math.PI/180)+this.f*Math.sin(i*Math.PI/180))/Math.sqrt(this.a*this.a+this.b*this.b),transformedY:(this.f*Math.cos(i*Math.PI/180)+this.e*Math.sin(-i*Math.PI/180))/Math.sqrt(this.c*this.c+this.d*this.d),skewX:-i,skewY:180/Math.PI*Math.atan2(e.y,e.x),scaleX:Math.sqrt(this.a*this.a+this.b*this.b),scaleY:Math.sqrt(this.c*this.c+this.d*this.d),rotation:i,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f,matrix:new w.Matrix(this)}},clone:function(){return new w.Matrix(this)},morph:function(t){return this.destination=new w.Matrix(t),this},at:function(t){if(!this.destination)return this;var e=new w.Matrix({a:this.a+(this.destination.a-this.a)*t,b:this.b+(this.destination.b-this.b)*t,c:this.c+(this.destination.c-this.c)*t,d:this.d+(this.destination.d-this.d)*t,e:this.e+(this.destination.e-this.e)*t,f:this.f+(this.destination.f-this.f)*t});return e},multiply:function(t){return new w.Matrix(this.native().multiply(d(t).native()))},inverse:function(){return new w.Matrix(this.native().inverse())},translate:function(t,e){return new w.Matrix(this.native().translate(t||0,e||0))},scale:function(t,e,i,n){return 1==arguments.length?e=t:3==arguments.length&&(n=i,i=e,e=t),this.around(i,n,new w.Matrix(t,0,0,e,0,0))},rotate:function(t,e,i){return t=w.utils.radians(t),this.around(e,i,new w.Matrix(Math.cos(t),Math.sin(t),-Math.sin(t),Math.cos(t),0,0))},flip:function(t,e){return e="number"==typeof t?t:e,"x"==t?this.scale(-1,1,e,0):"y"==t?this.scale(1,-1,0,e):this.scale(-1,-1,e,e)},skew:function(t,e,i,n){return 1==arguments.length?e=t:3==arguments.length&&(n=i,i=e,e=t),t=w.utils.radians(t),e=w.utils.radians(e),this.around(i,n,new w.Matrix(1,Math.tan(e),Math.tan(t),1,0,0))},skewX:function(t,e,i){return this.skew(t,0,e,i)},skewY:function(t,e,i){return this.skew(0,t,e,i)},around:function(t,e,i){return this.multiply(new w.Matrix(1,0,0,1,t||0,e||0)).multiply(i).multiply(new w.Matrix(1,0,0,1,-t||0,-e||0))},native:function(){for(var t=w.parser.native.createSVGMatrix(),e=C.length-1;e>=0;e--)t[C[e]]=this[C[e]];return t},toString:function(){return"matrix("+this.a+","+this.b+","+this.c+","+this.d+","+this.e+","+this.f+")"}},parent:w.Element,construct:{ctm:function(){return new w.Matrix(this.node.getCTM())},screenCTM:function(){if(this instanceof w.Nested){var t=this.rect(1,1),e=t.node.getScreenCTM();return t.remove(),new w.Matrix(e)}return new w.Matrix(this.node.getScreenCTM())}}}),w.Point=w.invent({create:function(t,e){var i,n={x:0,y:0};i=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}:n,this.x=i.x,this.y=i.y},extend:{clone:function(){return new w.Point(this)},morph:function(t,e){return this.destination=new w.Point(t,e),this},at:function(t){if(!this.destination)return this; -var e=new w.Point({x:this.x+(this.destination.x-this.x)*t,y:this.y+(this.destination.y-this.y)*t});return e},native:function(){var t=w.parser.native.createSVGPoint();return t.x=this.x,t.y=this.y,t},transform:function(t){return new w.Point(this.native().matrixTransform(t.native()))}}}),w.extend(w.Element,{point:function(t,e){return new w.Point(t,e).transform(this.screenCTM().inverse())}}),w.extend(w.Element,{attr:function(t,e,i){if(null==t){for(t={},e=this.node.attributes,i=e.length-1;i>=0;i--)t[e[i].nodeName]=w.regex.isNumber.test(e[i].nodeValue)?parseFloat(e[i].nodeValue):e[i].nodeValue;return t}if("object"==typeof t)for(e in t)this.attr(e,t[e]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return e=this.node.getAttribute(t),null==e?w.defaults.attrs[t]:w.regex.isNumber.test(e)?parseFloat(e):e;"fill"!=t&&"stroke"!=t||(w.regex.isImage.test(e)&&(e=this.doc().defs().image(e,0,0)),e instanceof w.Image&&(e=this.doc().defs().pattern(0,0,function(){this.add(e)}))),"number"==typeof e?e=new w.Number(e):w.Color.isColor(e)?e=new w.Color(e):Array.isArray(e)&&(e=new w.Array(e)),"leading"==t?this.leading&&this.leading(e):"string"==typeof i?this.node.setAttributeNS(i,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!=t&&"x"!=t||this.rebuild(t,e)}return this}}),w.extend(w.Element,{transform:function(t,e){var i,n=this;if("object"!=typeof t)return i=new w.Matrix(n).extract(),"string"==typeof t?i[t]:i;if(i=new w.Matrix(n),e=!!e||!!t.relative,null!=t.a)i=e?i.multiply(new w.Matrix(t)):new w.Matrix(t);else if(null!=t.rotation)p(t,n),i=e?i.rotate(t.rotation,t.cx,t.cy):i.rotate(t.rotation-i.extract().rotation,t.cx,t.cy);else if(null!=t.scale||null!=t.scaleX||null!=t.scaleY){if(p(t,n),t.scaleX=null!=t.scale?t.scale:null!=t.scaleX?t.scaleX:1,t.scaleY=null!=t.scale?t.scale:null!=t.scaleY?t.scaleY:1,!e){var r=i.extract();t.scaleX=1*t.scaleX/r.scaleX,t.scaleY=1*t.scaleY/r.scaleY}i=i.scale(t.scaleX,t.scaleY,t.cx,t.cy)}else if(null!=t.skew||null!=t.skewX||null!=t.skewY){if(p(t,n),t.skewX=null!=t.skew?t.skew:null!=t.skewX?t.skewX:0,t.skewY=null!=t.skew?t.skew:null!=t.skewY?t.skewY:0,!e){var r=i.extract();i=i.multiply((new w.Matrix).skew(r.skewX,r.skewY,t.cx,t.cy).inverse())}i=i.skew(t.skewX,t.skewY,t.cx,t.cy)}else t.flip?i=i.flip(t.flip,null==t.offset?n.bbox()["c"+t.flip]:t.offset):null==t.x&&null==t.y||(e?i=i.translate(t.x,t.y):(null!=t.x&&(i.e=t.x),null!=t.y&&(i.f=t.y)));return this.attr("transform",i)}}),w.extend(w.FX,{transform:function(t,e){var i,n=this.target();return"object"!=typeof t?(i=new w.Matrix(n).extract(),"string"==typeof t?i[t]:i):(e=!!e||!!t.relative,null!=t.a?i=new w.Matrix(t):null!=t.rotation?(p(t,n),i=new w.Rotate(t.rotation,t.cx,t.cy)):null!=t.scale||null!=t.scaleX||null!=t.scaleY?(p(t,n),t.scaleX=null!=t.scale?t.scale:null!=t.scaleX?t.scaleX:1,t.scaleY=null!=t.scale?t.scale:null!=t.scaleY?t.scaleY:1,i=new w.Scale(t.scaleX,t.scaleY,t.cx,t.cy)):null!=t.skewX||null!=t.skewY?(p(t,n),t.skewX=null!=t.skewX?t.skewX:0,t.skewY=null!=t.skewY?t.skewY:0,i=new w.Skew(t.skewX,t.skewY,t.cx,t.cy)):t.flip?i=(new w.Matrix).flip(t.flip,null==t.offset?n.bbox()["c"+t.flip]:t.offset):null==t.x&&null==t.y||(i=new w.Translate(t.x,t.y)),i?(i.relative=e,this.last().transforms.push(i),this._callStart()):this)}}),w.extend(w.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){var t=(this.attr("transform")||"").split(/\)\s*,?\s*/).slice(0,-1).map(function(t){var e=t.trim().split("(");return[e[0],e[1].split(w.regex.matrixElements).map(function(t){return parseFloat(t)})]}).reduce(function(t,e){return"matrix"==e[0]?t.multiply(f(e[1])):t[e[0]].apply(t,e[1])},new w.Matrix);return t},toParent:function(t){if(this==t)return this;var e=this.screenCTM(),i=t.screenCTM().inverse();return this.addTo(t).untransform().transform(i.multiply(e)),this},toDoc:function(){return this.toParent(this.doc())}}),w.Transformation=w.invent({create:function(t,e){if(arguments.length>1&&"boolean"!=typeof e)return this.constructor.call(this,[].slice.call(arguments));if(Array.isArray(t))for(var i=0,n=this.arguments.length;i=0},index:function(t){return[].slice.call(this.node.childNodes).indexOf(t.node)},get:function(t){return w.adopt(this.node.childNodes[t])},first:function(){return this.get(0)},last:function(){return this.get(this.node.childNodes.length-1)},each:function(t,e){var i,n,r=this.children();for(i=0,n=r.length;in/r?this.height/r:this.width/n,this.x=e,this.y=i,this.width=n,this.height=r)}else t="string"==typeof t?t.match(f).map(function(t){return parseFloat(t)}):Array.isArray(t)?t:"object"==typeof t?[t.x,t.y,t.width,t.height]:4==arguments.length?[].slice.call(arguments):u,this.x=t[0],this.y=t[1],this.width=t[2],this.height=t[3]},extend:{toString:function(){return this.x+" "+this.y+" "+this.width+" "+this.height},morph:function(t,e,i,n){return this.destination=new w.ViewBox(t,e,i,n),this},at:function(t){return this.destination?new w.ViewBox([this.x+(this.destination.x-this.x)*t,this.y+(this.destination.y-this.y)*t,this.width+(this.destination.width-this.width)*t,this.height+(this.destination.height-this.height)*t]):this}},parent:w.Container,construct:{viewbox:function(t,e,i,n){return 0==arguments.length?new w.ViewBox(this):this.attr("viewBox",new w.ViewBox(t,e,i,n))}}}),["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","touchstart","touchmove","touchleave","touchend","touchcancel"].forEach(function(t){w.Element.prototype[t]=function(e){var i=this;return this.node["on"+t]="function"==typeof e?function(){return e.apply(i,arguments)}:null,this}}),w.listeners=[],w.handlerMap=[],w.listenerId=0,w.on=function(t,e,i,n){var r=i.bind(n||t.instance||t),s=(w.handlerMap.indexOf(t)+1||w.handlerMap.push(t))-1,o=e.split(".")[0],a=e.split(".")[1]||"*";w.listeners[s]=w.listeners[s]||{},w.listeners[s][o]=w.listeners[s][o]||{},w.listeners[s][o][a]=w.listeners[s][o][a]||{},i._svgjsListenerId||(i._svgjsListenerId=++w.listenerId),w.listeners[s][o][a][i._svgjsListenerId]=r,t.addEventListener(o,r,!1)},w.off=function(t,e,i){var n=w.handlerMap.indexOf(t),r=e&&e.split(".")[0],s=e&&e.split(".")[1];if(n!=-1)if(i){if("function"==typeof i&&(i=i._svgjsListenerId),!i)return;w.listeners[n][r]&&w.listeners[n][r][s||"*"]&&(t.removeEventListener(r,w.listeners[n][r][s||"*"][i],!1),delete w.listeners[n][r][s||"*"][i])}else if(s&&r){if(w.listeners[n][r]&&w.listeners[n][r][s]){for(i in w.listeners[n][r][s])w.off(t,[r,s].join("."),i);delete w.listeners[n][r][s]}}else if(s)for(e in w.listeners[n])for(namespace in w.listeners[n][e])s===namespace&&w.off(t,[e,s].join("."));else if(r){if(w.listeners[n][r]){for(namespace in w.listeners[n][r])w.off(t,[r,namespace].join("."));delete w.listeners[n][r]}}else{for(e in w.listeners[n])w.off(t,e);delete w.listeners[n],delete w.handlerMap[n]}},w.extend(w.Element,{on:function(t,e,i){return w.on(this.node,t,e,i),this},off:function(t,e){return w.off(this.node,t,e),this},fire:function(t,e){return t instanceof Event?this.node.dispatchEvent(t):this.node.dispatchEvent(t=new CustomEvent(t,{detail:e,cancelable:!0})),this._event=t,this},event:function(){return this._event}}),w.Defs=w.invent({create:"defs",inherit:w.Container}),w.G=w.invent({create:"g",inherit:w.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 w.G)}}}),w.extend(w.Element,{siblings:function(){return this.parent().children()},position:function(){return this.parent().index(this)},next:function(){return this.siblings()[this.position()+1]},previous:function(){return this.siblings()[this.position()-1]},forward:function(){var t=this.position()+1,e=this.parent();return e.removeElement(this).add(this,t),e instanceof w.Doc&&e.node.appendChild(e.defs().node),this},backward:function(){var t=this.position();return t>0&&this.parent().removeElement(this).add(this,t-1),this},front:function(){var t=this.parent();return t.node.appendChild(this.node),t instanceof w.Doc&&t.node.appendChild(t.defs().node),this},back:function(){return this.position()>0&&this.parent().removeElement(this).add(this,0),this},before:function(t){t.remove();var e=this.position();return this.parent().add(t,e),this},after:function(t){t.remove();var e=this.position();return this.parent().add(t,e+1),this}}),w.Mask=w.invent({create:"mask",inherit:w.Container,extend:{remove:function(){return this.targets().each(function(){this.unmask()}),this.parent().removeElement(this),this},targets:function(){return w.select('svg [mask*="'+this.id()+'"]')}},construct:{mask:function(){return this.defs().put(new w.Mask)}}}),w.extend(w.Element,{maskWith:function(t){var e=t instanceof w.Mask?t:this.parent().mask().add(t);return this.attr("mask",'url("#'+e.attr("id")+'")')},unmask:function(){return this.attr("mask",null)},masker:function(){return this.reference("mask")}}),w.ClipPath=w.invent({create:"clipPath",inherit:w.Container,extend:{remove:function(){return this.targets().each(function(){this.unclip()}),this.parent().removeElement(this),this},targets:function(){return w.select('svg [clip-path*="'+this.id()+'"]')}},construct:{clip:function(){return this.defs().put(new w.ClipPath)}}}),w.extend(w.Element,{clipWith:function(t){var e=t instanceof w.ClipPath?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.attr("id")+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}),w.Gradient=w.invent({create:function(t){this.constructor.call(this,w.create(t+"Gradient"))},inherit:w.Container,extend:{at:function(t,e,i){return this.put(new w.Stop).update(t,e,i)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},fill:function(){return"url(#"+this.id()+")"},toString:function(){return this.fill()},attr:function(t,e,i){return"transform"==t&&(t="gradientTransform"),w.Container.prototype.attr.call(this,t,e,i)}},construct:{gradient:function(t,e){return this.defs().gradient(t,e)}}}),w.extend(w.Gradient,w.FX,{from:function(t,e){return"radialGradient"==(this._target||this).type?this.attr({fx:new w.Number(t),fy:new w.Number(e)}):this.attr({x1:new w.Number(t),y1:new w.Number(e)})},to:function(t,e){return"radialGradient"==(this._target||this).type?this.attr({cx:new w.Number(t),cy:new w.Number(e)}):this.attr({x2:new w.Number(t),y2:new w.Number(e)})}}),w.extend(w.Defs,{gradient:function(t,e){return this.put(new w.Gradient(t)).update(e)}}),w.Stop=w.invent({create:"stop",inherit:w.Element,extend:{update:function(t){return("number"==typeof t||t instanceof w.Number)&&(t={offset:arguments[0],color:arguments[1],opacity:arguments[2]}),null!=t.opacity&&this.attr("stop-opacity",t.opacity),null!=t.color&&this.attr("stop-color",t.color),null!=t.offset&&this.attr("offset",new w.Number(t.offset)),this}}}),w.Pattern=w.invent({create:"pattern",inherit:w.Container,extend:{fill:function(){return"url(#"+this.id()+")"},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return this.fill()},attr:function(t,e,i){return"transform"==t&&(t="patternTransform"),w.Container.prototype.attr.call(this,t,e,i)}},construct:{pattern:function(t,e,i){return this.defs().pattern(t,e,i)}}}),w.extend(w.Defs,{pattern:function(t,e,i){return this.put(new w.Pattern).update(i).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}),w.Doc=w.invent({create:function(t){t&&(t="string"==typeof t?e.getElementById(t):t,"svg"==t.nodeName?this.constructor.call(this,t):(this.constructor.call(this,w.create("svg")),t.appendChild(this.node),this.size("100%","100%")),this.namespace().defs())},inherit:w.Container,extend:{namespace:function(){return this.attr({xmlns:w.ns,version:"1.1"}).attr("xmlns:xlink",w.xlink,w.xmlns).attr("xmlns:svgjs",w.svgjs,w.xmlns)},defs:function(){if(!this._defs){var t;(t=this.node.getElementsByTagName("defs")[0])?this._defs=w.adopt(t):this._defs=new w.Defs,this.node.appendChild(this._defs.node)}return this._defs},parent:function(){return"#document"==this.node.parentNode.nodeName?null:this.node.parentNode},spof:function(t){var e=this.node.getScreenCTM();return e&&this.style("left",-e.e%1+"px").style("top",-e.f%1+"px"),this},remove:function(){return this.parent()&&this.parent().removeChild(this.node),this}}}),w.Shape=w.invent({create:function(t){this.constructor.call(this,t)},inherit:w.Element}),w.Bare=w.invent({create:function(t,e){if(this.constructor.call(this,w.create(t)),e)for(var i in e.prototype)"function"==typeof e.prototype[i]&&(this[i]=e.prototype[i])},inherit:w.Element,extend:{words:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(e.createTextNode(t)),this}}}),w.extend(w.Parent,{element:function(t,e){return this.put(new w.Bare(t,e))}}),w.Symbol=w.invent({create:"symbol",inherit:w.Container,construct:{symbol:function(){return this.put(new w.Symbol)}}}),w.Use=w.invent({create:"use",inherit:w.Shape,extend:{element:function(t,e){return this.attr("href",(e||"")+"#"+t,w.xlink)}},construct:{use:function(t,e){return this.put(new w.Use).element(t,e)}}}),w.Rect=w.invent({create:"rect",inherit:w.Shape,construct:{rect:function(t,e){return this.put(new w.Rect).size(t,e)}}}),w.Circle=w.invent({create:"circle",inherit:w.Shape,construct:{circle:function(t){return this.put(new w.Circle).rx(new w.Number(t).divide(2)).move(0,0)}}}),w.extend(w.Circle,w.FX,{rx:function(t){return this.attr("r",t)},ry:function(t){return this.rx(t)}}),w.Ellipse=w.invent({create:"ellipse",inherit:w.Shape,construct:{ellipse:function(t,e){return this.put(new w.Ellipse).size(t,e).move(0,0)}}}),w.extend(w.Ellipse,w.Rect,w.FX,{rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)}}),w.extend(w.Circle,w.Ellipse,{x:function(t){return null==t?this.cx()-this.rx():this.cx(t+this.rx())},y:function(t){return null==t?this.cy()-this.ry():this.cy(t+this.ry())},cx:function(t){return null==t?this.attr("cx"):this.attr("cx",t)},cy:function(t){return null==t?this.attr("cy"):this.attr("cy",t)},width:function(t){return null==t?2*this.rx():this.rx(new w.Number(t).divide(2))},height:function(t){return null==t?2*this.ry():this.ry(new w.Number(t).divide(2))},size:function(t,e){var i=l(this,t,e);return this.rx(new w.Number(i.width).divide(2)).ry(new w.Number(i.height).divide(2))}}),w.Line=w.invent({create:"line",inherit:w.Shape,extend:{array:function(){return new w.PointArray([[this.attr("x1"),this.attr("y1")],[this.attr("x2"),this.attr("y2")]])},plot:function(t,e,i,n){return null==t?this.array():(t="undefined"!=typeof e?{x1:t,y1:e,x2:i,y2:n}:new w.PointArray(t).toLine(),this.attr(t))},move:function(t,e){return this.attr(this.array().move(t,e).toLine())},size:function(t,e){var i=l(this,t,e);return this.attr(this.array().size(i.width,i.height).toLine())}},construct:{line:function(t,e,i,n){return w.Line.prototype.plot.apply(this.put(new w.Line),null!=t?[t,e,i,n]:[0,0,0,0])}}}),w.Polyline=w.invent({create:"polyline",inherit:w.Shape,construct:{polyline:function(t){return this.put(new w.Polyline).plot(t||new w.PointArray)}}}),w.Polygon=w.invent({create:"polygon",inherit:w.Shape,construct:{polygon:function(t){return this.put(new w.Polygon).plot(t||new w.PointArray)}}}),w.extend(w.Polyline,w.Polygon,{array:function(){return this._array||(this._array=new w.PointArray(this.attr("points")))},plot:function(t){return null==t?this.array():this.attr("points",this._array=new w.PointArray(t))},move:function(t,e){return this.attr("points",this.array().move(t,e))},size:function(t,e){var i=l(this,t,e);return this.attr("points",this.array().size(i.width,i.height))}}),w.extend(w.Line,w.Polyline,w.Polygon,{morphArray:w.PointArray,x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},width:function(t){var e=this.bbox();return null==t?e.width:this.size(t,e.height)},height:function(t){var e=this.bbox();return null==t?e.height:this.size(e.width,t)}}),w.Path=w.invent({create:"path",inherit:w.Shape,extend:{morphArray:w.PathArray,array:function(){return this._array||(this._array=new w.PathArray(this.attr("d")))},plot:function(t){return null==t?this.array():this.attr("d",this._array=new w.PathArray(t))},move:function(t,e){return this.attr("d",this.array().move(t,e))},x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},size:function(t,e){var i=l(this,t,e);return this.attr("d",this.array().size(i.width,i.height))},width:function(t){return null==t?this.bbox().width:this.size(t,this.bbox().height)},height:function(t){return null==t?this.bbox().height:this.size(this.bbox().width,t)}},construct:{path:function(t){return this.put(new w.Path).plot(t||new w.PathArray)}}}),w.Image=w.invent({create:"image",inherit:w.Shape,extend:{load:function(t){if(!t)return this;var i=this,n=e.createElement("img");return n.onload=function(){var e=i.parent(w.Pattern);null!==e&&(0==i.width()&&0==i.height()&&i.size(n.width,n.height),e&&0==e.width()&&0==e.height()&&e.size(i.width(),i.height()),"function"==typeof i._loaded&&i._loaded.call(i,{width:n.width,height:n.height,ratio:n.width/n.height,url:t}))},n.onerror=function(t){"function"==typeof i._error&&i._error.call(i,t)},this.attr("href",n.src=this.src=t,w.xlink)},loaded:function(t){return this._loaded=t,this},error:function(t){return this._error=t,this}},construct:{image:function(t,e,i){return this.put(new w.Image).load(t).size(e||0,i||e||0)}}}),w.Text=w.invent({create:function(){this.constructor.call(this,w.create("text")),this.dom.leading=new w.Number(1.3),this._rebuild=!0,this._build=!1,this.attr("font-family",w.defaults.attrs["font-family"])},inherit:w.Shape,extend:{x:function(t){return null==t?this.attr("x"):this.attr("x",t)},y:function(t){var e=this.attr("y"),i="number"==typeof e?e-this.bbox().y:0;return null==t?"number"==typeof e?e-i:e:this.attr("y","number"==typeof t?t+i:t)},cx:function(t){return null==t?this.bbox().cx:this.x(t-this.bbox().width/2)},cy:function(t){return null==t?this.bbox().cy:this.y(t-this.bbox().height/2)},text:function(t){if("undefined"==typeof t){for(var t="",e=this.node.childNodes,i=0,n=e.length;i=0;e--)null!=i[b[t][e]]&&this.attr(b.prefix(t,b[t][e]),i[b[t][e]]);return this},w.extend(w.Element,w.FX,i)}),w.extend(w.Element,w.FX,{rotate:function(t,e,i){return this.transform({rotation:t,cx:e,cy:i})},skew:function(t,e,i,n){return 1==arguments.length||3==arguments.length?this.transform({skew:t,cx:e,cy:i}):this.transform({skewX:t,skewY:e,cx:i,cy:n})},scale:function(t,e,i,n){return 1==arguments.length||3==arguments.length?this.transform({scale:t,cx:e,cy:i}):this.transform({scaleX:t,scaleY:e,cx:i,cy:n})},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})},matrix:function(t){return this.attr("transform",new w.Matrix(6==arguments.length?[].slice.call(arguments):t))},opacity:function(t){return this.attr("opacity",t)},dx:function(t){return this.x(new w.Number(t).plus(this instanceof w.FX?0:this.x()),!0)},dy:function(t){return this.y(new w.Number(t).plus(this instanceof w.FX?0:this.y()),!0)},dmove:function(t,e){return this.dx(t).dy(e)}}),w.extend(w.Rect,w.Ellipse,w.Circle,w.Gradient,w.FX,{radius:function(t,e){var i=(this._target||this).type;return"radialGradient"==i||"radialGradient"==i?this.attr("r",new w.Number(t)):this.rx(t).ry(null==e?t:e)}}),w.extend(w.Path,{length:function(){return this.node.getTotalLength()},pointAt:function(t){return new w.Point(this.node.getPointAtLength(t))}}),w.extend(w.Parent,w.Text,w.Tspan,w.FX,{font:function(t,e){if("object"==typeof t)for(e in t)this.font(e,t[e]);return"leading"==t?this.leading(e):"anchor"==t?this.attr("text-anchor",e):"size"==t||"family"==t||"weight"==t||"stretch"==t||"variant"==t||"style"==t?this.attr("font-"+t,e):this.attr(t,e)}}),w.Set=w.invent({create:function(t){Array.isArray(t)?this.members=t:this.clear()},extend:{add:function(){var t,e,i=[].slice.call(arguments);for(t=0,e=i.length;t-1&&this.members.splice(e,1),this},each:function(t){for(var e=0,i=this.members.length;e=0},index:function(t){return this.members.indexOf(t)},get:function(t){return this.members[t]},first:function(){return this.get(0)},last:function(){return this.get(this.members.length-1)},valueOf:function(){return this.members},bbox:function(){if(0==this.members.length)return new w.RBox;var t=this.members[0].rbox(this.members[0].doc());return this.each(function(){t=t.merge(this.rbox(this.doc()))}),t}},construct:{set:function(t){return new w.Set(t)}}}),w.FX.Set=w.invent({create:function(t){this.set=t}}),w.Set.inherit=function(){var t,e=[];for(var t in w.Shape.prototype)"function"==typeof w.Shape.prototype[t]&&"function"!=typeof w.Set.prototype[t]&&e.push(t);e.forEach(function(t){w.Set.prototype[t]=function(){for(var e=0,i=this.members.length;e=0;t--)delete this.memory()[arguments[t]];return this},memory:function(){return this._memory||(this._memory={})}}),w.get=function(t){var i=e.getElementById(g(t)||t);return w.adopt(i)},w.select=function(t,i){return new w.Set(w.utils.map((i||e).querySelectorAll(t),function(t){return w.adopt(t)}))},w.$$=function(t,i){return w.utils.map((i||e).querySelectorAll(t),function(t){return w.adopt(t)})},w.$=function(t,i){return w.adopt((i||e).querySelector(t))},w.extend(w.Parent,{select:function(t){return w.select(t,this.node)}});var C="abcdef".split("");return w}); \ No newline at end of file +/*! svg.js v2.5.0 MIT*/;!function(t,e){"function"==typeof define&&define.amd?define(function(){return e(t,t.document)}):"object"==typeof exports?module.exports=t.document?e(t,t.document):function(t){return e(t,t.document)}:t.SVG=e(t,t.document)}("undefined"!=typeof window?window:this,function(t,e){function i(t){return!(t.w||t.h||t.x||t.y)}function n(t){return(e.documentElement.contains||function(t){for(;t.parentNode;)t=t.parentNode;return t==e}).call(e.documentElement,t)}function r(t,e,i,n){return i+n.replace(C.regex.dots," .")}function s(t){for(var e=t.slice(0),i=e.length;i--;)Array.isArray(e[i])&&(e[i]=s(e[i]));return e}function a(t,e){return t instanceof e}function o(t,e){return(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)}function h(t){return t.toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()})}function u(t){return t.charAt(0).toUpperCase()+t.slice(1)}function l(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 c(t){var e=t.toString(16);return 1==e.length?"0"+e:e}function f(t,e,i){if(null==e||null==i){var n=t.bbox();null==e?e=n.width/n.height*i:null==i&&(i=n.height/n.width*e)}return{width:e,height:i}}function d(t,e,i){return{x:e*t.a+i*t.c+0,y:e*t.b+i*t.d+0}}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 C.Matrix||(t=new C.Matrix(t)),t}function x(t,e){t.cx=null==t.cx?e.bbox().cx:t.cx,t.cy=null==t.cy?e.bbox().cy:t.cy}function y(t){return t=t.replace(C.regex.whitespace,"").replace(C.regex.matrix,"").split(C.regex.matrixElements),p(C.utils.map(t,function(t){return parseFloat(t)}))}function v(t){for(var e=0,i=t.length,n="";e=0;e--)t.childNodes[e]instanceof SVGElement&&g(t.childNodes[e]);return C.adopt(t).id(C.eid(t.nodeName))}function w(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 b(t){var e=(t||"").toString().match(C.regex.reference);if(e)return e[1]}var C=this.SVG=function(t){if(C.supported)return t=new C.Doc(t),C.parser.draw||C.prepare(),t};if(C.ns="http://www.w3.org/2000/svg",C.xmlns="http://www.w3.org/2000/xmlns/",C.xlink="http://www.w3.org/1999/xlink",C.svgjs="http://svgjs.com/svgjs",C.supported=function(){return!!e.createElementNS&&!!e.createElementNS(C.ns,"svg").createSVGRect}(),!C.supported)return!1;C.did=1e3,C.eid=function(t){return"Svgjs"+u(t)+C.did++},C.create=function(t){var i=e.createElementNS(this.ns,t);return i.setAttribute("id",this.eid(t)),i},C.extend=function(){var t,e,i,n;for(t=[].slice.call(arguments),e=t.pop(),n=t.length-1;n>=0;n--)if(t[n])for(i in e)t[n].prototype[i]=e[i];C.Set&&C.Set.inherit&&C.Set.inherit()},C.invent=function(t){var e="function"==typeof t.create?t.create:function(){this.constructor.call(this,C.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&C.extend(e,t.extend),t.construct&&C.extend(t.parent||C.Container,t.construct),e},C.adopt=function(t){if(!t)return null;if(t.instance)return t.instance;var e;return e="svg"==t.nodeName?t.parentNode instanceof SVGElement?new C.Nested:new C.Doc:"linearGradient"==t.nodeName?new C.Gradient("linear"):"radialGradient"==t.nodeName?new C.Gradient("radial"):C[u(t.nodeName)]?new(C[u(t.nodeName)]):new C.Element(t),e.type=t.nodeName,e.node=t,t.instance=e,e instanceof C.Doc&&e.namespace().defs(),e.setData(JSON.parse(t.getAttribute("svgjs:data"))||{}),e},C.prepare=function(){var t=e.getElementsByTagName("body")[0],i=(t?new C.Doc(t):new C.Doc(e.documentElement).nested()).size(2,0);C.parser={body:t||e.documentElement,draw:i.style("opacity:0;position:absolute;left:-100%;top:-100%;overflow:hidden"),poly:i.polyline().node,path:i.path().node,native:C.create("svg")}},C.parser={native:C.create("svg")},e.addEventListener("DOMContentLoaded",function(){C.parser.draw||C.prepare()},!1),C.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,matrix:/matrix\(|\)/g,matrixElements:/,*\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},C.utils={map:function(t,e){var i,n=t.length,r=[];for(i=0;i1?1:t,new C.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}}),C.Color.test=function(t){return t+="",C.regex.isHex.test(t)||C.regex.isRgb.test(t)},C.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},C.Color.isColor=function(t){return C.Color.isRgb(t)||C.Color.test(t)},C.Array=function(t,e){t=(t||[]).valueOf(),0==t.length&&e&&(t=e.valueOf()),this.value=this.parse(t)},C.extend(C.Array,{morph:function(t){if(this.destination=this.parse(t),this.value.length!=this.destination.length){for(var e=this.value[this.value.length-1],i=this.destination[this.destination.length-1];this.value.length>this.destination.length;)this.destination.push(i);for(;this.value.length=0;n--)this.value[n]=[this.value[n][0]+t,this.value[n][1]+e];return this},size:function(t,e){var i,n=this.bbox();for(i=this.value.length-1;i>=0;i--)n.width&&(this.value[i][0]=(this.value[i][0]-n.x)*t/n.width+n.x),n.height&&(this.value[i][1]=(this.value[i][1]-n.y)*e/n.height+n.y);return this},bbox:function(){return C.parser.poly.setAttribute("points",this.toString()),C.parser.poly.getBBox()}}),C.PathArray=function(t,e){C.Array.call(this,t,e||[["M",0,0]])},C.PathArray.prototype=new C.Array,C.PathArray.prototype.constructor=C.PathArray,C.extend(C.PathArray,{toString:function(){return v(this.value)},move:function(t,e){var i=this.bbox();if(t-=i.x,e-=i.y,!isNaN(t)&&!isNaN(e))for(var n,r=this.value.length-1;r>=0;r--)n=this.value[r][0],"M"==n||"L"==n||"T"==n?(this.value[r][1]+=t,this.value[r][2]+=e):"H"==n?this.value[r][1]+=t:"V"==n?this.value[r][1]+=e:"C"==n||"S"==n||"Q"==n?(this.value[r][1]+=t,this.value[r][2]+=e,this.value[r][3]+=t,this.value[r][4]+=e,"C"==n&&(this.value[r][5]+=t,this.value[r][6]+=e)):"A"==n&&(this.value[r][6]+=t,this.value[r][7]+=e);return this},size:function(t,e){var i,n,r=this.bbox();for(i=this.value.length-1;i>=0;i--)n=this.value[i][0],"M"==n||"L"==n||"T"==n?(this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x,this.value[i][2]=(this.value[i][2]-r.y)*e/r.height+r.y):"H"==n?this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x:"V"==n?this.value[i][1]=(this.value[i][1]-r.y)*e/r.height+r.y:"C"==n||"S"==n||"Q"==n?(this.value[i][1]=(this.value[i][1]-r.x)*t/r.width+r.x,this.value[i][2]=(this.value[i][2]-r.y)*e/r.height+r.y,this.value[i][3]=(this.value[i][3]-r.x)*t/r.width+r.x,this.value[i][4]=(this.value[i][4]-r.y)*e/r.height+r.y,"C"==n&&(this.value[i][5]=(this.value[i][5]-r.x)*t/r.width+r.x,this.value[i][6]=(this.value[i][6]-r.y)*e/r.height+r.y)):"A"==n&&(this.value[i][1]=this.value[i][1]*t/r.width,this.value[i][2]=this.value[i][2]*e/r.height,this.value[i][6]=(this.value[i][6]-r.x)*t/r.width+r.x,this.value[i][7]=(this.value[i][7]-r.y)*e/r.height+r.y);return this},equalCommands:function(t){var e,i,n;for(t=new C.PathArray(t),n=this.value.length===t.value.length,e=0,i=this.value.length;n&&ei.x&&e>i.y&&t/,"").replace(/<\/svg>$/,"");i.innerHTML=""+t.replace(/\n/,"").replace(/<(\w+)([^<]+?)\/>/g,"<$1$2>")+"";for(var n=0,r=i.firstChild.childNodes.length;n":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return-Math.cos(t*Math.PI/2)+1}},C.morph=function(t){return function(e,i){return new C.MorphObj(e,i).at(t)}},C.Situation=C.invent({create:function(t){this.init=!1,this.reversed=!1,this.reversing=!1,this.duration=new C.Number(t.duration).valueOf(),this.delay=new C.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={}}}),C.FX=C.invent({create:function(t){this._target=t,this.situations=[],this.active=!1,this.situation=null,this.paused=!1,this.lastPos=0,this.pos=0,this.absPos=0,this._speed=1},extend:{animate:function(t,e,i){"object"==typeof t&&(e=t.ease,i=t.delay,t=t.duration);var n=new C.Situation({duration:t||1e3,delay:i||0,ease:C.easing[e||"-"]||e});return this.queue(n),this},delay:function(t){var e=new C.Situation({duration:t,delay:0,ease:C.easing["-"]});return this.queue(e)},target:function(t){return t&&t instanceof C.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=requestAnimationFrame(function(){this.step()}.bind(this))},stopAnimFrame:function(){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 C.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 C.Situation?this.start():this.situation.call(this)),this},initAnimations:function(){var t,e,i=this.situation;if(i.init)return this;for(t in i.animations)e=this.target()[t](),i.animations[t]instanceof C.Number&&(e=new C.Number(e)),i.animations[t]=e.morph(i.animations[t]);for(t in i.attrs)i.attrs[t]=new C.MorphObj(this.target().attr(t),i.attrs[t]);for(t in i.styles)i.styles[t]=new C.MorphObj(this.target().style(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 i=this.active;return this.active=!1,e&&this.clearQueue(),t&&this.situation&&(!i&&this.startCurrent(),this.atEnd()),this.stopAnimFrame(),this.clearCurrent()},reset:function(){if(this.situation){var t=this.situation;this.stop(),this.situation=t,this.atStart()}return this},finish:function(){for(this.stop(!0,!1);this.dequeue().situation&&this.stop(!0,!1););return this.clearQueue().clearCurrent(),this},atStart:function(){return this.at(0,!0)},atEnd:function(){return this.situation.loops===!0&&(this.situation.loops=this.situation.loop+1),"number"==typeof this.situation.loops?this.at(this.situation.loops,!0):this.at(1,!0)},at:function(t,e){var i=this.situation.duration/this._speed;return this.absPos=t,e||(this.situation.reversed&&(this.absPos=1-this.absPos),this.absPos+=this.situation.loop),this.situation.start=+new Date-this.absPos*i,this.situation.finish=this.situation.start+i,this.step(!0)},speed:function(t){return 0===t?this.pause():t?(this._speed=t,this.at(this.absPos,!0)):this._speed},loop:function(t,e){var i=this.last();return i.loops=null==t||t,i.loop=0,e&&(i.reversing=!0),this},pause:function(){return this.paused=!0,this.stopAnimFrame(),this},play:function(){return this.paused?(this.paused=!1,this.at(this.absPos,!0)):this},reverse:function(t){var e=this.last();return"undefined"==typeof t?e.reversed=!e.reversed:e.reversed=t,this},progress:function(t){return t?this.situation.ease(this.pos):this.pos},after:function(t){var e=this.last(),i=function i(n){n.detail.situation==e&&(t.call(this,e),this.off("finished.fx",i))};return this.target().on("finished.fx",i),this._callStart()},during:function(t){var e=this.last(),i=function(i){i.detail.situation==e&&t.call(this,i.detail.pos,C.morph(i.detail.pos),i.detail.eased,e)};return this.target().off("during.fx",i).on("during.fx",i),this.after(function(){this.off("during.fx",i)}),this._callStart()},afterAll:function(t){var e=function e(i){t.call(this),this.off("allfinished.fx",e)};return this.target().off("allfinished.fx",e).on("allfinished.fx",e),this._callStart()},duringAll:function(t){var e=function(e){t.call(this,e.detail.pos,C.morph(e.detail.pos),e.detail.eased,e.detail.situation)};return this.target().off("during.fx",e).on("during.fx",e),this.afterAll(function(){this.off("during.fx",e)}),this._callStart()},last:function(){return this.situations.length?this.situations[this.situations.length-1]:this.situation},add:function(t,e,i){return this.last()[i||"animations"][t]=e,this._callStart()},step:function(t){if(t||(this.absPos=this.timeToAbsPos(+new Date)),this.situation.loops!==!1){var e,i,n;e=Math.max(this.absPos,0),i=Math.floor(e),this.situation.loops===!0||ithis.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.target().off(".fx"),this.active=!1),this.active?this.dequeue():this.clearCurrent()):!this.paused&&this.active&&this.startAnimFrame(),this.lastPos=r,this):this},eachAt:function(){var t,e,i=this,n=this.target(),r=this.situation;for(t in r.animations)e=[].concat(r.animations[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(i.pos),i.pos):t}),n[t].apply(n,e);for(t in r.attrs)e=[t].concat(r.attrs[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(i.pos),i.pos):t}),n.attr.apply(n,e);for(t in r.styles)e=[t].concat(r.styles[t]).map(function(t){return"string"!=typeof t&&t.at?t.at(r.ease(i.pos),i.pos):t}),n.style.apply(n,e);if(r.transforms.length){for(e=r.initialTransformation,t=0,len=r.transforms.length;t1?[].slice.call(arguments):arguments[0])},leading:function(t){return this.target().leading?this.add("leading",new C.Number(t)):this},viewbox:function(t,e,i,n){return this.target()instanceof C.Container&&this.add("viewbox",new C.Box(t,e,i,n)),this},update:function(t){if(this.target()instanceof C.Stop){if("number"==typeof t||t instanceof C.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}}),C.Matrix=C.invent({create:function(t){var e,i=p([1,0,0,1,0,0]);for(t=t instanceof C.Element?t.matrixify():"string"==typeof t?y(t):6==arguments.length?p([].slice.call(arguments)):Array.isArray(t)?p(t):"object"==typeof t?t:i,e=N.length-1;e>=0;--e)this[N[e]]=t&&"number"==typeof t[N[e]]?t[N[e]]:i[N[e]]},extend:{extract:function(){var t=d(this,0,1),e=d(this,1,0),i=180/Math.PI*Math.atan2(t.y,t.x)-90;return{x:this.e,y:this.f,transformedX:(this.e*Math.cos(i*Math.PI/180)+this.f*Math.sin(i*Math.PI/180))/Math.sqrt(this.a*this.a+this.b*this.b),transformedY:(this.f*Math.cos(i*Math.PI/180)+this.e*Math.sin(-i*Math.PI/180))/Math.sqrt(this.c*this.c+this.d*this.d),skewX:-i,skewY:180/Math.PI*Math.atan2(e.y,e.x),scaleX:Math.sqrt(this.a*this.a+this.b*this.b),scaleY:Math.sqrt(this.c*this.c+this.d*this.d),rotation:i,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f,matrix:new C.Matrix(this)}},clone:function(){return new C.Matrix(this)},morph:function(t){return this.destination=new C.Matrix(t),this},at:function(t){if(!this.destination)return this;var e=new C.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});return e},multiply:function(t){return new C.Matrix(this.native().multiply(m(t).native()))},inverse:function(){return new C.Matrix(this.native().inverse())},translate:function(t,e){return new C.Matrix(this.native().translate(t||0,e||0))},scale:function(t,e,i,n){return 1==arguments.length?e=t:3==arguments.length&&(n=i,i=e,e=t),this.around(i,n,new C.Matrix(t,0,0,e,0,0))},rotate:function(t,e,i){return t=C.utils.radians(t),this.around(e,i,new C.Matrix(Math.cos(t),Math.sin(t),-Math.sin(t),Math.cos(t),0,0))},flip:function(t,e){return e="number"==typeof t?t:e,"x"==t?this.scale(-1,1,e,0):"y"==t?this.scale(1,-1,0,e):this.scale(-1,-1,e,e)},skew:function(t,e,i,n){return 1==arguments.length?e=t:3==arguments.length&&(n=i,i=e,e=t),t=C.utils.radians(t),e=C.utils.radians(e),this.around(i,n,new C.Matrix(1,Math.tan(e),Math.tan(t),1,0,0))},skewX:function(t,e,i){return this.skew(t,0,e,i)},skewY:function(t,e,i){return this.skew(0,t,e,i)},around:function(t,e,i){return this.multiply(new C.Matrix(1,0,0,1,t||0,e||0)).multiply(i).multiply(new C.Matrix(1,0,0,1,-t||0,-e||0))},native:function(){for(var t=C.parser.native.createSVGMatrix(),e=N.length-1;e>=0;e--)t[N[e]]=this[N[e]];return t},toString:function(){return"matrix("+this.a+","+this.b+","+this.c+","+this.d+","+this.e+","+this.f+")"}},parent:C.Element,construct:{ctm:function(){return new C.Matrix(this.node.getCTM())},screenCTM:function(){if(this instanceof C.Nested){var t=this.rect(1,1),e=t.node.getScreenCTM();return t.remove(),new C.Matrix(e)}return new C.Matrix(this.node.getScreenCTM())}}}),C.Point=C.invent({create:function(t,e){var i,n={x:0,y:0};i=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}:n,this.x=i.x,this.y=i.y},extend:{clone:function(){return new C.Point(this)},morph:function(t,e){return this.destination=new C.Point(t,e),this},at:function(t){if(!this.destination)return this;var e=new C.Point({x:this.x+(this.destination.x-this.x)*t,y:this.y+(this.destination.y-this.y)*t});return e},native:function(){var t=C.parser.native.createSVGPoint();return t.x=this.x,t.y=this.y,t},transform:function(t){return new C.Point(this.native().matrixTransform(t.native()))}}}),C.extend(C.Element,{point:function(t,e){return new C.Point(t,e).transform(this.screenCTM().inverse())}}),C.extend(C.Element,{attr:function(t,e,i){if(null==t){for(t={},e=this.node.attributes,i=e.length-1;i>=0;i--)t[e[i].nodeName]=C.regex.isNumber.test(e[i].nodeValue)?parseFloat(e[i].nodeValue):e[i].nodeValue;return t}if("object"==typeof t)for(e in t)this.attr(e,t[e]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return e=this.node.getAttribute(t),null==e?C.defaults.attrs[t]:C.regex.isNumber.test(e)?parseFloat(e):e;"fill"!=t&&"stroke"!=t||(C.regex.isImage.test(e)&&(e=this.doc().defs().image(e,0,0)),e instanceof C.Image&&(e=this.doc().defs().pattern(0,0,function(){this.add(e)}))),"number"==typeof e?e=new C.Number(e):C.Color.isColor(e)?e=new C.Color(e):Array.isArray(e)&&(e=new C.Array(e)),"leading"==t?this.leading&&this.leading(e):"string"==typeof i?this.node.setAttributeNS(i,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!=t&&"x"!=t||this.rebuild(t,e)}return this}}),C.extend(C.Element,{transform:function(t,e){var i,n=this;if("object"!=typeof t)return i=new C.Matrix(n).extract(),"string"==typeof t?i[t]:i;if(i=new C.Matrix(n),e=!!e||!!t.relative,null!=t.a)i=e?i.multiply(new C.Matrix(t)):new C.Matrix(t);else if(null!=t.rotation)x(t,n),i=e?i.rotate(t.rotation,t.cx,t.cy):i.rotate(t.rotation-i.extract().rotation,t.cx,t.cy);else if(null!=t.scale||null!=t.scaleX||null!=t.scaleY){if(x(t,n),t.scaleX=null!=t.scale?t.scale:null!=t.scaleX?t.scaleX:1,t.scaleY=null!=t.scale?t.scale:null!=t.scaleY?t.scaleY:1,!e){var r=i.extract();t.scaleX=1*t.scaleX/r.scaleX,t.scaleY=1*t.scaleY/r.scaleY}i=i.scale(t.scaleX,t.scaleY,t.cx,t.cy); +}else if(null!=t.skew||null!=t.skewX||null!=t.skewY){if(x(t,n),t.skewX=null!=t.skew?t.skew:null!=t.skewX?t.skewX:0,t.skewY=null!=t.skew?t.skew:null!=t.skewY?t.skewY:0,!e){var r=i.extract();i=i.multiply((new C.Matrix).skew(r.skewX,r.skewY,t.cx,t.cy).inverse())}i=i.skew(t.skewX,t.skewY,t.cx,t.cy)}else t.flip?i=i.flip(t.flip,null==t.offset?n.bbox()["c"+t.flip]:t.offset):null==t.x&&null==t.y||(e?i=i.translate(t.x,t.y):(null!=t.x&&(i.e=t.x),null!=t.y&&(i.f=t.y)));return this.attr("transform",i)}}),C.extend(C.FX,{transform:function(t,e){var i,n=this.target();return"object"!=typeof t?(i=new C.Matrix(n).extract(),"string"==typeof t?i[t]:i):(e=!!e||!!t.relative,null!=t.a?i=new C.Matrix(t):null!=t.rotation?(x(t,n),i=new C.Rotate(t.rotation,t.cx,t.cy)):null!=t.scale||null!=t.scaleX||null!=t.scaleY?(x(t,n),t.scaleX=null!=t.scale?t.scale:null!=t.scaleX?t.scaleX:1,t.scaleY=null!=t.scale?t.scale:null!=t.scaleY?t.scaleY:1,i=new C.Scale(t.scaleX,t.scaleY,t.cx,t.cy)):null!=t.skewX||null!=t.skewY?(x(t,n),t.skewX=null!=t.skewX?t.skewX:0,t.skewY=null!=t.skewY?t.skewY:0,i=new C.Skew(t.skewX,t.skewY,t.cx,t.cy)):t.flip?i=(new C.Matrix).flip(t.flip,null==t.offset?n.bbox()["c"+t.flip]:t.offset):null==t.x&&null==t.y||(i=new C.Translate(t.x,t.y)),i?(i.relative=e,this.last().transforms.push(i),this._callStart()):this)}}),C.extend(C.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){var t=(this.attr("transform")||"").split(/\)\s*,?\s*/).slice(0,-1).map(function(t){var e=t.trim().split("(");return[e[0],e[1].split(C.regex.matrixElements).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 C.Matrix);return t},toParent:function(t){if(this==t)return this;var e=this.screenCTM(),i=t.screenCTM().inverse();return this.addTo(t).untransform().transform(i.multiply(e)),this},toDoc:function(){return this.toParent(this.doc())}}),C.Transformation=C.invent({create:function(t,e){if(arguments.length>1&&"boolean"!=typeof e)return this.constructor.call(this,[].slice.call(arguments));if(Array.isArray(t))for(var i=0,n=this.arguments.length;i=0},index:function(t){return[].slice.call(this.node.childNodes).indexOf(t.node)},get:function(t){return C.adopt(this.node.childNodes[t])},first:function(){return this.get(0)},last:function(){return this.get(this.node.childNodes.length-1)},each:function(t,e){var i,n,r=this.children();for(i=0,n=r.length;i0&&this.parent().removeElement(this).add(this,t-1),this},front:function(){var t=this.parent();return t.node.appendChild(this.node),t instanceof C.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}}),C.Mask=C.invent({create:"mask",inherit:C.Container,extend:{remove:function(){return this.targets().each(function(){this.unmask()}),this.parent().removeElement(this),this},targets:function(){return C.select('svg [mask*="'+this.id()+'"]')}},construct:{mask:function(){return this.defs().put(new C.Mask)}}}),C.extend(C.Element,{maskWith:function(t){var e=t instanceof C.Mask?t:this.parent().mask().add(t);return this.attr("mask",'url("#'+e.attr("id")+'")')},unmask:function(){return this.attr("mask",null)},masker:function(){return this.reference("mask")}}),C.ClipPath=C.invent({create:"clipPath",inherit:C.Container,extend:{remove:function(){return this.targets().each(function(){this.unclip()}),this.parent().removeElement(this),this},targets:function(){return C.select('svg [clip-path*="'+this.id()+'"]')}},construct:{clip:function(){return this.defs().put(new C.ClipPath)}}}),C.extend(C.Element,{clipWith:function(t){var e=t instanceof C.ClipPath?t:this.parent().clip().add(t);return this.attr("clip-path",'url("#'+e.attr("id")+'")')},unclip:function(){return this.attr("clip-path",null)},clipper:function(){return this.reference("clip-path")}}),C.Gradient=C.invent({create:function(t){this.constructor.call(this,C.create(t+"Gradient"))},inherit:C.Container,extend:{at:function(t,e,i){return this.put(new C.Stop).update(t,e,i)},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},fill:function(){return"url(#"+this.id()+")"},toString:function(){return this.fill()},attr:function(t,e,i){return"transform"==t&&(t="gradientTransform"),C.Container.prototype.attr.call(this,t,e,i)}},construct:{gradient:function(t,e){return this.defs().gradient(t,e)}}}),C.extend(C.Gradient,C.FX,{from:function(t,e){return"radialGradient"==(this._target||this).type?this.attr({fx:new C.Number(t),fy:new C.Number(e)}):this.attr({x1:new C.Number(t),y1:new C.Number(e)})},to:function(t,e){return"radialGradient"==(this._target||this).type?this.attr({cx:new C.Number(t),cy:new C.Number(e)}):this.attr({x2:new C.Number(t),y2:new C.Number(e)})}}),C.extend(C.Defs,{gradient:function(t,e){return this.put(new C.Gradient(t)).update(e)}}),C.Stop=C.invent({create:"stop",inherit:C.Element,extend:{update:function(t){return("number"==typeof t||t instanceof C.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 C.Number(t.offset)),this}}}),C.Pattern=C.invent({create:"pattern",inherit:C.Container,extend:{fill:function(){return"url(#"+this.id()+")"},update:function(t){return this.clear(),"function"==typeof t&&t.call(this,this),this},toString:function(){return this.fill()},attr:function(t,e,i){return"transform"==t&&(t="patternTransform"),C.Container.prototype.attr.call(this,t,e,i)}},construct:{pattern:function(t,e,i){return this.defs().pattern(t,e,i)}}}),C.extend(C.Defs,{pattern:function(t,e,i){return this.put(new C.Pattern).update(i).attr({x:0,y:0,width:t,height:e,patternUnits:"userSpaceOnUse"})}}),C.Doc=C.invent({create:function(t){t&&(t="string"==typeof t?e.getElementById(t):t,"svg"==t.nodeName?this.constructor.call(this,t):(this.constructor.call(this,C.create("svg")),t.appendChild(this.node),this.size("100%","100%")),this.namespace().defs())},inherit:C.Container,extend:{namespace:function(){return this.attr({xmlns:C.ns,version:"1.1"}).attr("xmlns:xlink",C.xlink,C.xmlns).attr("xmlns:svgjs",C.svgjs,C.xmlns)},defs:function(){if(!this._defs){var t;(t=this.node.getElementsByTagName("defs")[0])?this._defs=C.adopt(t):this._defs=new C.Defs,this.node.appendChild(this._defs.node)}return this._defs},parent:function(){return"#document"==this.node.parentNode.nodeName?null:this.node.parentNode},spof:function(t){var e=this.node.getScreenCTM();return e&&this.style("left",-e.e%1+"px").style("top",-e.f%1+"px"),this},remove:function(){return this.parent()&&this.parent().removeChild(this.node),this}}}),C.Shape=C.invent({create:function(t){this.constructor.call(this,t)},inherit:C.Element}),C.Bare=C.invent({create:function(t,e){if(this.constructor.call(this,C.create(t)),e)for(var i in e.prototype)"function"==typeof e.prototype[i]&&(this[i]=e.prototype[i])},inherit:C.Element,extend:{words:function(t){for(;this.node.hasChildNodes();)this.node.removeChild(this.node.lastChild);return this.node.appendChild(e.createTextNode(t)),this}}}),C.extend(C.Parent,{element:function(t,e){return this.put(new C.Bare(t,e))}}),C.Symbol=C.invent({create:"symbol",inherit:C.Container,construct:{symbol:function(){return this.put(new C.Symbol)}}}),C.Use=C.invent({create:"use",inherit:C.Shape,extend:{element:function(t,e){return this.attr("href",(e||"")+"#"+t,C.xlink)}},construct:{use:function(t,e){return this.put(new C.Use).element(t,e)}}}),C.Rect=C.invent({create:"rect",inherit:C.Shape,construct:{rect:function(t,e){return this.put(new C.Rect).size(t,e)}}}),C.Circle=C.invent({create:"circle",inherit:C.Shape,construct:{circle:function(t){return this.put(new C.Circle).rx(new C.Number(t).divide(2)).move(0,0)}}}),C.extend(C.Circle,C.FX,{rx:function(t){return this.attr("r",t)},ry:function(t){return this.rx(t)}}),C.Ellipse=C.invent({create:"ellipse",inherit:C.Shape,construct:{ellipse:function(t,e){return this.put(new C.Ellipse).size(t,e).move(0,0)}}}),C.extend(C.Ellipse,C.Rect,C.FX,{rx:function(t){return this.attr("rx",t)},ry:function(t){return this.attr("ry",t)}}),C.extend(C.Circle,C.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 C.Number(t).divide(2))},height:function(t){return null==t?2*this.ry():this.ry(new C.Number(t).divide(2))},size:function(t,e){var i=f(this,t,e);return this.rx(new C.Number(i.width).divide(2)).ry(new C.Number(i.height).divide(2))}}),C.Line=C.invent({create:"line",inherit:C.Shape,extend:{array:function(){return new C.PointArray([[this.attr("x1"),this.attr("y1")],[this.attr("x2"),this.attr("y2")]])},plot:function(t,e,i,n){return null==t?this.array():(t="undefined"!=typeof e?{x1:t,y1:e,x2:i,y2:n}:new C.PointArray(t).toLine(),this.attr(t))},move:function(t,e){return this.attr(this.array().move(t,e).toLine())},size:function(t,e){var i=f(this,t,e);return this.attr(this.array().size(i.width,i.height).toLine())}},construct:{line:function(t,e,i,n){return C.Line.prototype.plot.apply(this.put(new C.Line),null!=t?[t,e,i,n]:[0,0,0,0])}}}),C.Polyline=C.invent({create:"polyline",inherit:C.Shape,construct:{polyline:function(t){return this.put(new C.Polyline).plot(t||new C.PointArray)}}}),C.Polygon=C.invent({create:"polygon",inherit:C.Shape,construct:{polygon:function(t){return this.put(new C.Polygon).plot(t||new C.PointArray)}}}),C.extend(C.Polyline,C.Polygon,{array:function(){return this._array||(this._array=new C.PointArray(this.attr("points")))},plot:function(t){return null==t?this.array():this.attr("points",this._array=new C.PointArray(t))},move:function(t,e){return this.attr("points",this.array().move(t,e))},size:function(t,e){var i=f(this,t,e);return this.attr("points",this.array().size(i.width,i.height))}}),C.extend(C.Line,C.Polyline,C.Polygon,{morphArray:C.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)}}),C.Path=C.invent({create:"path",inherit:C.Shape,extend:{morphArray:C.PathArray,array:function(){return this._array||(this._array=new C.PathArray(this.attr("d")))},plot:function(t){return null==t?this.array():this.attr("d",this._array=new C.PathArray(t))},move:function(t,e){return this.attr("d",this.array().move(t,e))},x:function(t){return null==t?this.bbox().x:this.move(t,this.bbox().y)},y:function(t){return null==t?this.bbox().y:this.move(this.bbox().x,t)},size:function(t,e){var i=f(this,t,e);return this.attr("d",this.array().size(i.width,i.height))},width:function(t){return null==t?this.bbox().width:this.size(t,this.bbox().height)},height:function(t){return null==t?this.bbox().height:this.size(this.bbox().width,t)}},construct:{path:function(t){return this.put(new C.Path).plot(t||new C.PathArray)}}}),C.Image=C.invent({create:"image",inherit:C.Shape,extend:{load:function(t){if(!t)return this;var i=this,n=e.createElement("img");return n.onload=function(){var e=i.parent(C.Pattern);null!==e&&(0==i.width()&&0==i.height()&&i.size(n.width,n.height),e&&0==e.width()&&0==e.height()&&e.size(i.width(),i.height()),"function"==typeof i._loaded&&i._loaded.call(i,{width:n.width,height:n.height,ratio:n.width/n.height,url:t}))},n.onerror=function(t){"function"==typeof i._error&&i._error.call(i,t)},this.attr("href",n.src=this.src=t,C.xlink)},loaded:function(t){return this._loaded=t,this},error:function(t){return this._error=t,this}},construct:{image:function(t,e,i){return this.put(new C.Image).load(t).size(e||0,i||e||0)}}}),C.Text=C.invent({create:function(){this.constructor.call(this,C.create("text")),this.dom.leading=new C.Number(1.3),this._rebuild=!0,this._build=!1,this.attr("font-family",C.defaults.attrs["font-family"])},inherit:C.Shape,extend:{x:function(t){return null==t?this.attr("x"):this.attr("x",t)},y:function(t){var e=this.attr("y"),i="number"==typeof e?e-this.bbox().y:0;return null==t?"number"==typeof e?e-i:e:this.attr("y","number"==typeof t?t+i:t)},cx:function(t){return null==t?this.bbox().cx:this.x(t-this.bbox().width/2)},cy:function(t){return null==t?this.bbox().cy:this.y(t-this.bbox().height/2)},text:function(t){if("undefined"==typeof t){for(var t="",e=this.node.childNodes,i=0,n=e.length;i=0;e--)null!=i[M[t][e]]&&this.attr(M.prefix(t,M[t][e]),i[M[t][e]]);return this},C.extend(C.Element,C.FX,i)}),C.extend(C.Element,C.FX,{rotate:function(t,e,i){return this.transform({rotation:t,cx:e,cy:i})},skew:function(t,e,i,n){return 1==arguments.length||3==arguments.length?this.transform({skew:t,cx:e,cy:i}):this.transform({skewX:t,skewY:e,cx:i,cy:n})},scale:function(t,e,i,n){return 1==arguments.length||3==arguments.length?this.transform({scale:t,cx:e,cy:i}):this.transform({scaleX:t,scaleY:e,cx:i,cy:n})},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})},matrix:function(t){return this.attr("transform",new C.Matrix(6==arguments.length?[].slice.call(arguments):t))},opacity:function(t){return this.attr("opacity",t)},dx:function(t){return this.x(new C.Number(t).plus(this instanceof C.FX?0:this.x()),!0)},dy:function(t){return this.y(new C.Number(t).plus(this instanceof C.FX?0:this.y()),!0)},dmove:function(t,e){return this.dx(t).dy(e)}}),C.extend(C.Rect,C.Ellipse,C.Circle,C.Gradient,C.FX,{radius:function(t,e){var i=(this._target||this).type;return"radialGradient"==i||"radialGradient"==i?this.attr("r",new C.Number(t)):this.rx(t).ry(null==e?t:e)}}),C.extend(C.Path,{length:function(){return this.node.getTotalLength()},pointAt:function(t){return new C.Point(this.node.getPointAtLength(t))}}),C.extend(C.Parent,C.Text,C.Tspan,C.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)}}),C.Set=C.invent({create:function(t){Array.isArray(t)?this.members=t:this.clear()},extend:{add:function(){var t,e,i=[].slice.call(arguments);for(t=0,e=i.length;t-1&&this.members.splice(e,1),this},each:function(t){for(var e=0,i=this.members.length;e=0},index:function(t){return this.members.indexOf(t)},get:function(t){return this.members[t]},first:function(){return this.get(0)},last:function(){return this.get(this.members.length-1)},valueOf:function(){return this.members},bbox:function(){if(0==this.members.length)return new C.Box;var t=this.members[0].rbox(this.members[0].doc());return this.each(function(){t=t.merge(this.rbox(this.doc()))}),t}},construct:{set:function(t){return new C.Set(t)}}}),C.FX.Set=C.invent({create:function(t){this.set=t}}),C.Set.inherit=function(){var t,e=[];for(var t in C.Shape.prototype)"function"==typeof C.Shape.prototype[t]&&"function"!=typeof C.Set.prototype[t]&&e.push(t);e.forEach(function(t){C.Set.prototype[t]=function(){for(var e=0,i=this.members.length;e=0;t--)delete this.memory()[arguments[t]];return this},memory:function(){return this._memory||(this._memory={})}}),C.get=function(t){var i=e.getElementById(b(t)||t);return C.adopt(i)},C.select=function(t,i){return new C.Set(C.utils.map((i||e).querySelectorAll(t),function(t){return C.adopt(t)}))},C.$$=function(t,i){return C.utils.map((i||e).querySelectorAll(t),function(t){return C.adopt(t)})},C.$=function(t,i){return C.adopt((i||e).querySelector(t))},C.extend(C.Parent,{select:function(t){return C.select(t,this.node)}});var N="abcdef".split("");return C.Box=C.invent({create:function(t){var e=[0,0,0,0];t="string"==typeof t?t.split(C.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],w(this)},extend:{merge:function(t){var e=Math.min(this.x,t.x),i=Math.min(this.y,t.y);return new C.Box(e,i,Math.max(this.x+this.width,t.x+t.width)-e,Math.max(this.y+this.height,t.y+t.height)-i)},transform:function(t){var e=1/0,i=-(1/0),n=1/0,r=-(1/0),s=[new C.Point(this.x,this.y),new C.Point(this.x2,this.y),new C.Point(this.x,this.y2),new C.Point(this.x2,this.y2)];return s.forEach(function(s){s=s.transform(t),e=Math.min(e,s.x),i=Math.max(i,s.x),n=Math.min(n,s.y),r=Math.max(r,s.y)}),new C.Box(e,n,i-e,r-n)},addOffset:function(){return this.x+=t.pageXOffset,this.y+=t.pageYOffset,this},toString:function(){return this.x+" "+this.y+" "+this.width+" "+this.height},morph:function(t,e,i,n){return this.destination=new C.Box(t,e,i,n),this},at:function(t){return this.destination?new C.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:C.Element,construct:{bbox:function(){var t;try{if(t=this.node.getBBox(),i(t)&&!n(this.node))throw new Exception("Element not in the dom")}catch(i){try{var e=this.clone(C.parser.draw).show();t=e.node.getBBox(),e.remove()}catch(t){console.warn("Getting a bounding box of this element is not possible")}}return new C.Box(t)},rbox:function(t){try{var e=new C.Box(this.node.getBoundingClientRect());return t?e.transform(t.screenCTM().inverse()):e.addOffset()}catch(t){return new C.Box}}}}),C.extend(C.Doc,C.Nested,C.Symbol,C.Image,C.Pattern,C.Marker,C.ForeignObject,C.View,{viewbox:function(t,e,i,n){return null==t?new C.Box(this.attr("viewBox")):this.attr("viewBox",new C.Box(t,e,i,n))}}),C}); \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 368ef85..08ba58f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -40,7 +40,6 @@ var parts = [ , 'src/number.js' , 'src/element.js' , 'src/fx.js' -, 'src/boxes.js' , 'src/matrix.js' , 'src/point.js' , 'src/attr.js' @@ -49,7 +48,6 @@ var parts = [ , 'src/parent.js' , 'src/flatten.js' , 'src/container.js' -, 'src/viewbox.js' , 'src/event.js' , 'src/defs.js' , 'src/group.js' @@ -82,6 +80,7 @@ var parts = [ , 'src/selector.js' , 'src/helpers.js' , 'src/polyfill.js' +, 'src/boxes.js' ] gulp.task('clean', function() { diff --git a/spec/SpecRunner.html b/spec/SpecRunner.html index 52f156b..0dd3315 100644 --- a/spec/SpecRunner.html +++ b/spec/SpecRunner.html @@ -99,7 +99,6 @@ - diff --git a/spec/spec/boxes.js b/spec/spec/boxes.js index 9e9fc73..16dddb9 100644 --- a/spec/spec/boxes.js +++ b/spec/spec/boxes.js @@ -1,29 +1,81 @@ describe('Box', function() { - it('creates a new instance without passing anything', function() { - var box = new SVG.Box + describe('initialization', function() { + var box - expect(box instanceof SVG.Box).toBe(true) - expect(box).toEqual(jasmine.objectContaining({ - x:0, y:0, cx:0, cy:0, width:0, height:0 - })) - }) + it('creates a new box with default values', function() { + box = new SVG.Box - it('creates a new instance with 4 arguments given', function() { - var box = new SVG.Box(10, 20, 100, 50) + expect(box instanceof SVG.Box).toBe(true) + expect(box).toEqual(jasmine.objectContaining({ + x:0, y:0, cx:0, cy:0, width:0, height:0 + })) + }) - expect(box instanceof SVG.Box).toBe(true) - expect(box).toEqual(jasmine.objectContaining({ - x:10, y:20, cx:60, cy:45, width:100, height:50 - })) - }) + it('creates a new box from parsed string', function() { + box = new SVG.Box('10. 100 200 300') + expect(box.x).toBe(10) + expect(box.y).toBe(100) + expect(box.width).toBe(200) + expect(box.height).toBe(300) + expect(box.cx).toBe(110) + expect(box.cy).toBe(250) + expect(box.x2).toBe(210) + expect(box.y2).toBe(400) + }) + + it('creates a new box from parsed string with comma as delimiter', function() { + box = new SVG.Box('10,100, 200 , 300') + expect(box.x).toBe(10) + expect(box.y).toBe(100) + expect(box.width).toBe(200) + expect(box.height).toBe(300) + }) + + it('creates a new box from array', function() { + box = new SVG.Box([10, 100, 200, 300]) + + expect(box.x).toBe(10) + expect(box.y).toBe(100) + expect(box.width).toBe(200) + expect(box.height).toBe(300) + }) + + it('creates a new box from object', function() { + box = new SVG.Box({x:10, y:100, width:200, height:300}) + + expect(box.x).toBe(10) + expect(box.y).toBe(100) + expect(box.width).toBe(200) + expect(box.height).toBe(300) + }) + + it('creates a new box from object width left and top instead of x and y', function() { + box = new SVG.Box({left:10, top:100, width:200, height:300}) + + expect(box.x).toBe(10) + expect(box.y).toBe(100) + expect(box.width).toBe(200) + expect(box.height).toBe(300) + }) - it('creates a new instance with object given', function() { - var box = new SVG.Box({x:10, y:20, width: 100, height:50}) + it('creates a new viewbox from 4 arguments', function() { + box = new SVG.Box(10, 100, 200, 300) + + expect(box.x).toBe(10) + expect(box.y).toBe(100) + expect(box.width).toBe(200) + expect(box.height).toBe(300) + }) + + it('creates a new box from parsed string with exponential values', function() { + box = new SVG.Box('-1.12e1 1e-2 +2e2 +.3e+4') + + expect(box.x).toBe(-11.2) + expect(box.y).toBe(0.01) + expect(box.width).toBe(200) + expect(box.height).toBe(3000) + }) - expect(box instanceof SVG.Box).toBe(true) - expect(box).toEqual(jasmine.objectContaining({ - x:10, y:20, cx:60, cy:45, width:100, height:50 - })) }) describe('merge()', function() { @@ -32,7 +84,7 @@ describe('Box', function() { var box2 = new SVG.Box(300, 400, 100, 100) var box3 = new SVG.Box(500, 100, 100, 100) var merged = box1.merge(box2).merge(box3) - + expect(merged).toEqual(jasmine.objectContaining({ x: 50, y: 50, cx: 325, cy: 275, width: 550, height: 450 })) @@ -43,110 +95,68 @@ describe('Box', function() { var merged = box1.merge(box2) expect(box1).not.toBe(merged) expect(box2).not.toBe(merged) - + expect(merged instanceof SVG.Box).toBe(true) }) }) - + describe('transform()', function() { it('transforms the box with given matrix', function() { var box1 = new SVG.Box(50, 50, 100, 100).transform(new SVG.Matrix(1,0,0,1,20,20)) var box2 = new SVG.Box(50, 50, 100, 100).transform(new SVG.Matrix(2,0,0,2,0,0)) var box3 = new SVG.Box(-200, -200, 100, 100).transform(new SVG.Matrix(1,0,0,1,-20,-20)) - + expect(box1).toEqual(jasmine.objectContaining({ x: 70, y: 70, cx: 120, cy: 120, width: 100, height: 100 })) - + expect(box2).toEqual(jasmine.objectContaining({ x: 100, y: 100, cx: 200, cy: 200, width: 200, height: 200 })) - + expect(box3).toEqual(jasmine.objectContaining({ x: -220, y: -220, cx: -170, cy: -170, width: 100, height: 100 })) }) }) -}) - -describe('BBox', function() { - afterEach(function() { - draw.clear() - }) + describe('morph()', function() { + it('stores a given box for morphing', function() { + var box1 = new SVG.Box(10, 100, 200, 300) + , box2 = new SVG.Box(50, -100, 300, 300) - it('creates a new instance from an element', function() { - var rect = draw.rect(100, 100).move(100, 25) - var box = new SVG.BBox(rect) + box1.morph(box2) - expect(box).toEqual(jasmine.objectContaining({ - x: 100, y: 25, cx: 150, cy: 75, width: 100, height: 100 - })) - }) - - describe('merge()', function() { - it('returns an instance of SVG.BBox', function() { - var box1 = new SVG.BBox(50, 50, 100, 100) - var box2 = new SVG.BBox(300, 400, 100, 100) - var merged = box1.merge(box2) - - expect(merged instanceof SVG.BBox).toBe(true) + expect(box1.destination).toEqual(box2) }) - }) - -}) - -describe('TBox', function() { - - afterEach(function() { - draw.clear() - }) - - it('should map to RBox and be removed in 3.x', function() { - var rect = draw.rect(100, 100).move(100, 25) - var tbox = rect.tbox() + it('stores a clone, not the given viewbox itself', function() { + var box1 = new SVG.Box(10, 100, 200, 300) + , box2 = new SVG.Box(50, -100, 300, 300) - expect(tbox.x).toBe(100) - expect(tbox.y).toBe(25) + box1.morph(box2) - rect.transform({ scale: 1.5 }) - tbox = rect.tbox() - expect(tbox.x).toBe(75) - expect(tbox.y).toBe(0) - - rect.transform({ skewX: 5 }) - tbox = rect.tbox() - expect(tbox.x|0).toBe(68) - expect(tbox.y|0).toBe(0) + expect(box1.destination).not.toBe(box2) + }) }) -}) - -describe('RBox', function() { + describe('at()', function() { + it('returns a morphed box at a given position', function() { + var box1 = new SVG.Box(10, 100, 200, 300) + , box2 = new SVG.Box(50, -100, 300, 300) + , box3 = box1.morph(box2).at(0.5) - afterEach(function() { - draw.clear() - }) - - it('creates a new instance from an element', function() { - var rect = draw.rect(100, 100).move(100, 25) - var box = new SVG.RBox(rect).transform(rect.doc().screenCTM().inverse()).addOffset() - expect(box).toEqual(jasmine.objectContaining({ - x: 100, y: 25, cx: 150, cy: 75, width: 100, height: 100 - })) - }) - - describe('merge()', function() { - it('returns an instance of SVG.RBox', function() { - var box1 = new SVG.RBox(50, 50, 100, 100) - var box2 = new SVG.RBox(300, 400, 100, 100) - var merged = box1.merge(box2) - - expect(merged instanceof SVG.RBox).toBe(true) + expect(box1.toString()).toBe('10 100 200 300') + expect(box2.toString()).toBe('50 -100 300 300') + expect(box3.toString()).toBe('30 0 250 300') + }) + it('returns itself when no destination given', function() { + var box = new SVG.Box(10, 100, 200, 300) + expect(box.at(0.5)).toBe(box) }) }) }) + describe('Boxes', function() { var rect, nested, offset @@ -161,8 +171,8 @@ describe('Boxes', function() { }) describe('bbox()', function() { - it('returns an instance of SVG.BBox', function() { - expect(rect.bbox() instanceof SVG.BBox).toBeTruthy() + it('returns an instance of SVG.Box', function() { + expect(rect.bbox() instanceof SVG.Box).toBeTruthy() }) it('matches the size of the target element, ignoring transformations', function() { var box = rect.bbox() @@ -194,8 +204,8 @@ describe('Boxes', function() { }) describe('rbox()', function() { - it('returns an instance of SVG.RBox', function() { - expect(rect.rbox() instanceof SVG.RBox).toBeTruthy() + it('returns an instance of SVG.Box', function() { + expect(rect.rbox() instanceof SVG.Box).toBeTruthy() }) it('returns the elements box in absolute screen coordinates by default', function() { @@ -224,6 +234,41 @@ describe('Boxes', function() { }) }) + describe('viewbox()', function() { + + beforeEach(function() { + draw.attr('viewBox', null) + }) + + it('should set the viewbox when four arguments are provided', function() { + draw.viewbox(0,0,100,100) + expect(draw.node.getAttribute('viewBox')).toBe('0 0 100 100') + }) + it('should set the viewbox when an object is provided as first argument', function() { + draw.viewbox({ x: 0, y: 0, width: 50, height: 50 }) + expect(draw.node.getAttribute('viewBox')).toBe('0 0 50 50') + }) + it('should set the viewbox when a string is provided as first argument', function() { + draw.viewbox('0 0 50 50') + expect(draw.node.getAttribute('viewBox')).toBe('0 0 50 50') + }) + it('should set the viewbox when an array is provided as first argument', function() { + draw.viewbox([0, 0, 50, 50]) + expect(draw.node.getAttribute('viewBox')).toBe('0 0 50 50') + }) + it('should accept negative values', function() { + draw.size(100,100).viewbox(-100, -100, 50, 50) + expect(draw.node.getAttribute('viewBox')).toEqual('-100 -100 50 50') + }) + it('should get the viewbox if no arguments are given', function() { + draw.viewbox(0, 0, 100, 100) + expect(draw.viewbox()).toEqual(new SVG.Box(0,0,100,100)) + }) + it('should get a nulled viewbox when no viewbox attribute is set', function() { + expect(draw.viewbox()).toEqual(new SVG.Box()) + }) + }) + }) diff --git a/spec/spec/element.js b/spec/spec/element.js index 7f7cd95..7afd791 100644 --- a/spec/spec/element.js +++ b/spec/spec/element.js @@ -571,9 +571,9 @@ describe('Element', function() { }) describe('rbox()', function() { - it('returns an instance of SVG.RBox', function() { + it('returns an instance of SVG.Box', function() { var rect = draw.rect(100,100) - expect(rect.rbox() instanceof SVG.RBox).toBe(true) + expect(rect.rbox() instanceof SVG.Box).toBe(true) }) it('returns the correct rectangular box', function() { var rect = draw.size(200, 150).viewbox(0, 0, 200, 150).rect(105, 210).move(2, 12) diff --git a/spec/spec/set.js b/spec/spec/set.js index 50c3126..0e0db1c 100644 --- a/spec/spec/set.js +++ b/spec/spec/set.js @@ -144,12 +144,12 @@ describe('Set', function() { expect(box.width).toBeCloseTo(300) expect(box.height).toBeCloseTo(350) }) - it('returns an instance of SVG.RBox', function() { + it('returns an instance of SVG.Box', function() { set.add(e1).add(e2).add(e3).add(e4).add(e5) - expect(set.bbox() instanceof SVG.RBox).toBeTruthy() + expect(set.bbox() instanceof SVG.Box).toBeTruthy() }) - it('returns an empty bounding box wiht no members', function() { + it('returns an empty bounding box with no members', function() { var box = set.bbox() expect(box.x).toBe(0) diff --git a/spec/spec/viewbox.js b/spec/spec/viewbox.js deleted file mode 100644 index cf6ec5c..0000000 --- a/spec/spec/viewbox.js +++ /dev/null @@ -1,162 +0,0 @@ -describe('Viewbox', function() { - var viewbox - - beforeEach(function() { - draw.clear() - }) - - describe('initialization', function() { - - - it('creates a new viewbox with default values', function() { - viewbox = new SVG.ViewBox() - - expect(viewbox.x).toBe(0) - expect(viewbox.y).toBe(0) - expect(viewbox.width).toBe(0) - expect(viewbox.height).toBe(0) - }) - - - - it('creates a new viewbox from parsed string', function() { - viewbox = new SVG.ViewBox('10. 100 200 300') - - expect(viewbox.x).toBe(10) - expect(viewbox.y).toBe(100) - expect(viewbox.width).toBe(200) - expect(viewbox.height).toBe(300) - }) - - - - it('creates a new viewbox from array', function() { - viewbox = new SVG.ViewBox([10, 100, 200, 300]) - - expect(viewbox.x).toBe(10) - expect(viewbox.y).toBe(100) - expect(viewbox.width).toBe(200) - expect(viewbox.height).toBe(300) - }) - - - - it('creates a new viewbox from object', function() { - viewbox = new SVG.ViewBox({x:10, y:100, width:200, height:300}) - - expect(viewbox.x).toBe(10) - expect(viewbox.y).toBe(100) - expect(viewbox.width).toBe(200) - expect(viewbox.height).toBe(300) - }) - - - - it('creates a new viewbox from 4 arguments given', function() { - viewbox = new SVG.ViewBox(10, 100, 200, 300) - - expect(viewbox.x).toBe(10) - expect(viewbox.y).toBe(100) - expect(viewbox.width).toBe(200) - expect(viewbox.height).toBe(300) - }) - - - it('creates a new viewbox from parsed string with exponential values', function() { - viewbox = new SVG.ViewBox('-1.12e1 1e-2 +2e2 +.3e+4') - - expect(viewbox.x).toBe(-11.2) - expect(viewbox.y).toBe(0.01) - expect(viewbox.width).toBe(200) - expect(viewbox.height).toBe(3000) - }) - - it('creates a new viewbox with element given', function() { - draw.attr('viewBox', '-1.12e1 1e-2 +2e2 +.3e+4') - viewbox = new SVG.ViewBox(draw) - - expect(viewbox.x).toBe(-11.2) - expect(viewbox.y).toBe(0.01) - expect(viewbox.width).toBe(200) - expect(viewbox.height).toBe(3000) - }) - - }) - - - describe('viewbox()', function() { - - beforeEach(function() { - draw.attr('viewBox', null) - }) - afterEach(function() { - draw.attr('viewBox', null) - }) - - it('should set the viewbox when four arguments are provided', function() { - draw.viewbox(0,0,100,100) - expect(draw.node.getAttribute('viewBox')).toBe('0 0 100 100') - }) - it('should set the viewbox when an object is provided as first argument', function() { - draw.viewbox({ x: 0, y: 0, width: 50, height: 50 }) - expect(draw.node.getAttribute('viewBox')).toBe('0 0 50 50') - }) - it('should set the viewbox when a string is provided as first argument', function() { - draw.viewbox('0 0 50 50') - expect(draw.node.getAttribute('viewBox')).toBe('0 0 50 50') - }) - it('should set the viewbox when an array is provided as first argument', function() { - draw.viewbox([0, 0, 50, 50]) - expect(draw.node.getAttribute('viewBox')).toBe('0 0 50 50') - }) - it('should accept negative values', function() { - draw.size(100,100).viewbox(-100, -100, 50, 50) - expect(draw.node.getAttribute('viewBox')).toEqual('-100 -100 50 50') - }) - it('should get the viewbox if no arguments are given', function() { - draw.viewbox(0, 0, 100, 100) - expect(draw.viewbox()).toEqual(new SVG.ViewBox(draw)) - }) - it('should define the zoom of the viewbox in relation to the canvas size', function() { - draw.size(100,100).viewbox(0,0,50,50) - expect(draw.viewbox().zoom).toEqual(100 / 50) - }) - - }) - - describe('morph()', function() { - it('stores a given viewbox for morphing', function() { - var viewbox1 = new SVG.ViewBox(10, 100, 200, 300) - , viewbox2 = new SVG.ViewBox(50, -100, 300, 300) - - viewbox1.morph(viewbox2) - - expect(viewbox1.destination).toEqual(viewbox2) - }) - it('stores a clone, not the given viewbox itself', function() { - var viewbox1 = new SVG.ViewBox(10, 100, 200, 300) - , viewbox2 = new SVG.ViewBox(50, -100, 300, 300) - - viewbox1.morph(viewbox2) - - expect(viewbox1.destination).not.toBe(viewbox2) - }) - }) - - describe('at()', function() { - it('returns a morphed viewbox at a given position', function() { - var viewbox1 = new SVG.ViewBox(10, 100, 200, 300) - , viewbox2 = new SVG.ViewBox(50, -100, 300, 300) - , viewbox3 = viewbox1.morph(viewbox2).at(0.5) - - expect(viewbox1.toString()).toBe('10 100 200 300') - expect(viewbox2.toString()).toBe('50 -100 300 300') - expect(viewbox3.toString()).toBe('30 0 250 300') - }) - it('returns itself when no destination given', function() { - var viewbox = new SVG.ViewBox(10, 100, 200, 300) - expect(viewbox.at(0.5)).toBe(viewbox) - }) - }) - -}) \ No newline at end of file diff --git a/src/boxes.js b/src/boxes.js index 3db523e..5ab261a 100644 --- a/src/boxes.js +++ b/src/boxes.js @@ -1,15 +1,20 @@ SVG.Box = SVG.invent({ - create: function(x, y, width, height) { - if (typeof x == 'object' && !(x instanceof SVG.Element)) { - // chromes getBoundingClientRect has no x and y property - return SVG.Box.call(this, x.left != null ? x.left : x.x , x.top != null ? x.top : x.y, x.width, x.height) - } else if (arguments.length == 4) { - this.x = x - this.y = y - this.width = width - this.height = height - - } + create: function(source) { + var base = [0,0,0,0] + source = typeof source === 'string' ? + source.split(SVG.regex.delimiter).map(parseFloat) : + Array.isArray(source) ? + source : + typeof source == 'object' ? + [source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height] : + arguments.length == 4 ? + [].slice.call(arguments) : + base + + this.x = source[0] + this.y = source[1] + this.width = source[2] + this.height = source[3] // add center, right, bottom... fullBox(this) @@ -17,15 +22,14 @@ SVG.Box = SVG.invent({ , extend: { // Merge rect box with another, return a new instance merge: function(box) { - var b = new this.constructor() - - // merge boxes - b.x = Math.min(this.x, box.x) - b.y = Math.min(this.y, box.y) - b.width = Math.max(this.x + this.width, box.x + box.width) - b.x - b.height = Math.max(this.y + this.height, box.y + box.height) - b.y - - return fullBox(b) + var x = Math.min(this.x, box.x) + , y = Math.min(this.y, box.y) + + return new SVG.Box( + x, y, + Math.max(this.x + this.width, box.x + box.width) - x, + Math.max(this.y + this.height, box.y + box.height) - y + ) } , transform: function(m) { @@ -46,124 +50,89 @@ SVG.Box = SVG.invent({ yMax = Math.max(yMax,p.y) }) - bbox = new this.constructor() - bbox.x = xMin - bbox.width = xMax-xMin - bbox.y = yMin - bbox.height = yMax-yMin - - fullBox(bbox) - - return bbox + return new SVG.Box( + xMin, yMin, + xMax-xMin, + yMax-yMin + ) } - } -}) -SVG.BBox = SVG.invent({ - // Initialize - create: function(element) { - SVG.Box.apply(this, [].slice.call(arguments)) - - // get values if element is given - if (element instanceof SVG.Element) { - var box + , addOffset: function() { + // offset by window scroll position, because getBoundingClientRect changes when window is scrolled + this.x += window.pageXOffset + 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 + } - // yes this is ugly, but Firefox can be a bitch when it comes to elements that are not yet rendered - try { + , at: function(pos) { - if (!document.documentElement.contains){ - // This is IE - it does not support contains() for top-level SVGs - var topParent = element.node; - while (topParent.parentNode){ - topParent = topParent.parentNode; - } - if (topParent != document) throw new Exception('Element not in the dom') - } else { - // the element is NOT in the dom, throw error - if(!document.documentElement.contains(element.node)) throw new Exception('Element not in the dom') - } + if(!this.destination) return this - // find native bbox - box = element.node.getBBox() - } catch(e) { - if(element instanceof SVG.Shape){ - var clone = element.clone(SVG.parser.draw).show() - box = clone.bbox() - clone.remove() - }else{ - box = { - x: element.node.clientLeft - , y: element.node.clientTop - , width: element.node.clientWidth - , height: element.node.clientHeight - } - } - } + 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 + ) - SVG.Box.call(this, box) } - } - // Define ancestor -, inherit: SVG.Box - - // Define Parent + // Define Parent , parent: SVG.Element // Constructor , construct: { // Get bounding box bbox: function() { - return new SVG.BBox(this) - } - } - -}) - -SVG.BBox.prototype.constructor = SVG.BBox - + var box -SVG.extend(SVG.Element, { - tbox: function(){ - console.warn('Use of TBox is deprecated and mapped to RBox. Use .rbox() instead.') - return this.rbox(this.doc()) - } -}) + try { + // find native bbox + box = this.node.getBBox() -SVG.RBox = SVG.invent({ - // Initialize - create: function(element) { - SVG.Box.apply(this, [].slice.call(arguments)) + if(isNulledBox(box) && !domContains(this.node)) { + throw new Exception('Element not in the dom') + } + } catch(e) { + try { + var clone = this.clone(SVG.parser.draw).show() + box = clone.node.getBBox() + clone.remove() + } catch(e) { + console.warn('Getting a bounding box of this element is not possible') + } + } - if (element instanceof SVG.Element) { - SVG.Box.call(this, element.node.getBoundingClientRect()) + return new SVG.Box(box) } - } - -, inherit: SVG.Box - - // define Parent -, parent: SVG.Element -, extend: { - addOffset: function() { - // offset by window scroll position, because getBoundingClientRect changes when window is scrolled - this.x += window.pageXOffset - this.y += window.pageYOffset - return this + , rbox: function(el) { + // IE11 throws an error when element not in dom + try{ + var box = new SVG.Box(this.node.getBoundingClientRect()) + if (el) return box.transform(el.screenCTM().inverse()) + return box.addOffset() + } catch(e) { + return new SVG.Box() + } } } +}) - // Constructor -, construct: { - // Get rect box - rbox: function(el) { - if (el) return new SVG.RBox(this).transform(el.screenCTM().inverse()) - return new SVG.RBox(this).addOffset() - } - } +SVG.extend(SVG.Doc, SVG.Nested, SVG.Symbol, SVG.Image, SVG.Pattern, SVG.Marker, SVG.ForeignObject, SVG.View, { + viewbox: function(x, y, width, height) { + // act as getter + if(x == null) return new SVG.Box(this.attr('viewBox')) + // act as setter + return this.attr('viewBox', new SVG.Box(x, y, width, height)) + } }) - -SVG.RBox.prototype.constructor = SVG.RBox diff --git a/src/fx.js b/src/fx.js index 98ded65..9fbbdd8 100644 --- a/src/fx.js +++ b/src/fx.js @@ -858,7 +858,7 @@ SVG.extend(SVG.FX, { // Add animatable viewbox , viewbox: function(x, y, width, height) { if (this.target() instanceof SVG.Container) { - this.add('viewbox', new SVG.ViewBox(x, y, width, height)) + this.add('viewbox', new SVG.Box(x, y, width, height)) } return this diff --git a/src/helpers.js b/src/helpers.js index b04c506..41f9620 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -1,3 +1,17 @@ +function isNulledBox(box) { + return !box.w && !box.h && !box.x && !box.y +} + +function domContains(node) { + return (document.documentElement.contains || function(node) { + // This is IE - it does not support contains() for top-level SVGs + while (node.parentNode){ + node = node.parentNode; + } + return node == document + }).call(document.documentElement, node) +} + function pathRegReplace(a, b, c, d) { return c + d.replace(SVG.regex.dots, ' .') } @@ -185,4 +199,4 @@ function idFromReference(url) { } // Create matrix array for looping -var abcdef = 'abcdef'.split('') \ No newline at end of file +var abcdef = 'abcdef'.split('') diff --git a/src/set.js b/src/set.js index 9da52c7..677916d 100644 --- a/src/set.js +++ b/src/set.js @@ -72,17 +72,17 @@ SVG.Set = SVG.invent({ , bbox: function(){ // return an empty box of there are no members if (this.members.length == 0) - return new SVG.RBox() + return new SVG.Box() // get the first rbox and update the target bbox - var rbox = this.members[0].rbox(this.members[0].doc()) + var box = this.members[0].rbox(this.members[0].doc()) this.each(function() { // user rbox for correct position and visual representation - rbox = rbox.merge(this.rbox(this.doc())) + box = box.merge(this.rbox(this.doc())) }) - return rbox + return box } } diff --git a/src/viewbox.js b/src/viewbox.js deleted file mode 100644 index 8ce7e04..0000000 --- a/src/viewbox.js +++ /dev/null @@ -1,127 +0,0 @@ - -SVG.ViewBox = SVG.invent({ - - create: function(source) { - var i, base = [0, 0, 0, 0] - - var x, y, width, height, box, view, we, he - , wm = 1 // width multiplier - , hm = 1 // height multiplier - , reg = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/gi - - if(source instanceof SVG.Element){ - - we = source - he = source - view = (source.attr('viewBox') || '').match(reg) - box = source.bbox - - // get dimensions of current node - width = new SVG.Number(source.width()) - height = new SVG.Number(source.height()) - - // find nearest non-percentual dimensions - while (width.unit == '%') { - wm *= width.value - width = new SVG.Number(we instanceof SVG.Doc ? we.parent().offsetWidth : we.parent().width()) - we = we.parent() - } - while (height.unit == '%') { - hm *= height.value - height = new SVG.Number(he instanceof SVG.Doc ? he.parent().offsetHeight : he.parent().height()) - he = he.parent() - } - - // ensure defaults - this.x = 0 - this.y = 0 - this.width = width * wm - this.height = height * hm - this.zoom = 1 - - if (view) { - // get width and height from viewbox - x = parseFloat(view[0]) - y = parseFloat(view[1]) - width = parseFloat(view[2]) - height = parseFloat(view[3]) - - // calculate zoom accoring to viewbox - this.zoom = ((this.width / this.height) > (width / height)) ? - this.height / height : - this.width / width - - // calculate real pixel dimensions on parent SVG.Doc element - this.x = x - this.y = y - this.width = width - this.height = height - - } - - }else{ - - // ensure source as object - source = typeof source === 'string' ? - source.match(reg).map(function(el){ return parseFloat(el) }) : - Array.isArray(source) ? - source : - typeof source == 'object' ? - [source.x, source.y, source.width, source.height] : - arguments.length == 4 ? - [].slice.call(arguments) : - base - - this.x = source[0] - this.y = source[1] - this.width = source[2] - this.height = source[3] - } - - - } - -, extend: { - - toString: function() { - return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height - } - , morph: function(x, y, width, height){ - this.destination = new SVG.ViewBox(x, y, width, height) - return this - } - - , at: function(pos) { - - if(!this.destination) return this - - return new SVG.ViewBox([ - 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 -, parent: SVG.Container - - // Add parent method -, construct: { - - // get/set viewbox - viewbox: function(x, y, width, height) { - if (arguments.length == 0) - // act as a getter if there are no arguments - return new SVG.ViewBox(this) - - // otherwise act as a setter - return this.attr('viewBox', new SVG.ViewBox(x, y, width, height)) - } - - } - -}) \ No newline at end of file -- 2.39.5