diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/boxes.js | 98 | ||||
-rwxr-xr-x | src/fx.js | 19 | ||||
-rwxr-xr-x | src/group.js | 4 | ||||
-rw-r--r-- | src/helpers.js | 213 | ||||
-rw-r--r-- | src/matrix.js | 19 | ||||
-rw-r--r-- | src/transform.js | 19 |
6 files changed, 212 insertions, 160 deletions
diff --git a/src/boxes.js b/src/boxes.js index 96c4246..2c5cd8b 100755 --- a/src/boxes.js +++ b/src/boxes.js @@ -1,23 +1,14 @@ SVG.BBox = SVG.invent({ // Initialize create: function(element) { - var box - - // Initialize zero box - this.x = 0 - this.y = 0 - this.width = 0 - this.height = 0 - - // Get values if element is given + // get values if element is given if (element) { - // Get current extracted transformations - var t = new SVG.Matrix(element).extract() - - // Find native bbox + var box + + // find native bbox if (element.node.getBBox) box = element.node.getBBox() - // Mimic bbox + // mimic bbox else box = { x: element.node.clientLeft @@ -26,55 +17,80 @@ SVG.BBox = SVG.invent({ , height: element.node.clientHeight } - // Include translations on x an y + // plain x and y + this.x = box.x + this.y = box.y + + // plain width and height + this.width = box.width + this.height = box.height + } + + // add center, right and bottom + fullBox(this) + } + + // Define Parent +, parent: SVG.Element + + // Constructor +, construct: { + // Get bounding box + bbox: function() { + return new SVG.BBox(this) + } + } + +}) + +SVG.TBox = SVG.invent({ + // Initialize + create: function(element) { + // get values if element is given + if (element) { + var t = element.ctm().extract() + , box = element.bbox() + + // x and y including transformations this.x = box.x + t.x this.y = box.y + t.y - // Plain width and height + // width and height including transformations this.width = box.width * t.scaleX this.height = box.height * t.scaleY } - // Add center, right and bottom + // add center, right and bottom fullBox(this) } - // define Parent + // Define Parent , parent: SVG.Element // Constructor , construct: { - // Get bounding box - bbox: function() { - return new SVG.BBox(this) + // Get transformed bounding box + tbox: function() { + return new SVG.TBox(this) } } }) + SVG.RBox = SVG.invent({ // Initialize create: function(element) { - var box = {} - - // Initialize zero box - this.x = 0 - this.y = 0 - this.width = 0 - this.height = 0 - if (element) { - var e = element.doc().parent() + var e = element.doc().parent() + , box = element.node.getBoundingClientRect() , zoom = 1 - // Actual, native bounding box - box = element.node.getBoundingClientRect() - - // Get screen offset + // get screen offset this.x = box.left this.y = box.top - // Subtract parent offset + // subtract parent offset this.x -= e.offsetLeft this.y -= e.offsetTop @@ -83,7 +99,7 @@ SVG.RBox = SVG.invent({ this.y -= e.offsetTop } - // Calculate cumulative zoom from svg documents + // calculate cumulative zoom from svg documents e = element while (e.parent && (e = e.parent())) { if (e.viewbox) { @@ -94,15 +110,15 @@ SVG.RBox = SVG.invent({ } } - // Recalculate viewbox distortion + // recalculate viewbox distortion this.width = box.width /= zoom this.height = box.height /= zoom - // Offset by window scroll position, because getBoundingClientRect changes when window is scrolled + // offset by window scroll position, because getBoundingClientRect changes when window is scrolled this.x += window.scrollX this.y += window.scrollY - // Add center, right and bottom + // add center, right and bottom fullBox(this) } @@ -120,14 +136,14 @@ SVG.RBox = SVG.invent({ }) // Add universal merge method -;[SVG.BBox, SVG.RBox].forEach(function(c) { +;[SVG.BBox, SVG.TBox, SVG.RBox].forEach(function(c) { SVG.extend(c, { // Merge rect box with another, return a new instance merge: function(box) { var b = new c() - // Merge box + // 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 @@ -222,13 +222,18 @@ SVG.FX = SVG.invent({ var from = this.target.attr(a) // detect format - this.attrs[a] = a == 'transform' ? - this.target.ctm().morph(v) : - SVG.Color.isColor(v) ? - new SVG.Color(from).morph(v) : - SVG.regex.unit.test(v) ? - new SVG.Number(from).morph(v) : - { from: from, to: v } + if (a == 'transform') { + if (this.attrs[a]) + v = this.attrs[a].destination.multiply(v) + + this.attrs[a] = this.target.ctm().morph(v) + } else { + this.attrs[a] = SVG.Color.isColor(v) ? + new SVG.Color(from).morph(v) : + SVG.regex.unit.test(v) ? + new SVG.Number(from).morph(v) : + { from: from, to: v } + } } return this diff --git a/src/group.js b/src/group.js index 66a8437..1b61371 100755 --- a/src/group.js +++ b/src/group.js @@ -17,11 +17,11 @@ SVG.G = SVG.invent({ } // Move by center over x-axis , cx: function(x) { - return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2) + return x == null ? this.tbox().cx : this.x(x - this.tbox().width / 2) } // Move by center over y-axis , cy: function(y) { - return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2) + return y == null ? this.tbox().cy : this.y(y - this.tbox().height / 2) } } diff --git a/src/helpers.js b/src/helpers.js index 8b11a00..70f189f 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -1,156 +1,165 @@ // Convert dash-separated-string to camelCase function camelCase(s) { - return s.toLowerCase().replace(/-(.)/g, function(m, g) { - return g.toUpperCase() - }) + return s.toLowerCase().replace(/-(.)/g, function(m, g) { + return g.toUpperCase() + }) } // Capitalize first letter of a string function capitalize(s) { - return s.charAt(0).toUpperCase() + s.slice(1) + return s.charAt(0).toUpperCase() + s.slice(1) } // Ensure to six-based hex function fullHex(hex) { - return hex.length == 4 ? - [ '#', - hex.substring(1, 2), hex.substring(1, 2) - , hex.substring(2, 3), hex.substring(2, 3) - , hex.substring(3, 4), hex.substring(3, 4) - ].join('') : hex + return hex.length == 4 ? + [ '#', + hex.substring(1, 2), hex.substring(1, 2) + , hex.substring(2, 3), hex.substring(2, 3) + , hex.substring(3, 4), hex.substring(3, 4) + ].join('') : hex } // Component to hex value function compToHex(comp) { - var hex = comp.toString(16) - return hex.length == 1 ? '0' + hex : hex + var hex = comp.toString(16) + return hex.length == 1 ? '0' + hex : hex } // Calculate proportional width and height values when necessary function proportionalSize(box, width, height) { - if (height == null) - height = box.height / box.width * width - else if (width == null) - width = box.width / box.height * height - - return { - width: width - , height: height - } + if (height == null) + height = box.height / box.width * width + else if (width == null) + width = box.width / box.height * height + + return { + width: width + , height: height + } } // Delta transform point function deltaTransformPoint(matrix, x, y) { - return { - x: x * matrix.a + y * matrix.c + 0 - , y: x * matrix.b + y * matrix.d + 0 - } + return { + x: x * matrix.a + y * matrix.c + 0 + , y: x * matrix.b + y * matrix.d + 0 + } } // Map matrix array to object function arrayToMatrix(a) { - return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] } + return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] } } // Parse matrix if required function parseMatrix(matrix) { - if (!(matrix instanceof SVG.Matrix)) - matrix = new SVG.Matrix(matrix) - - return matrix + if (!(matrix instanceof SVG.Matrix)) + matrix = new SVG.Matrix(matrix) + + return matrix } // Convert string to matrix function stringToMatrix(source) { - // remove matrix wrapper and split to individual numbers - source = source - .replace(SVG.regex.whitespace, '') - .replace(SVG.regex.matrix, '') - .split(',') - - // convert string values to floats and convert to a matrix-formatted object - return arrayToMatrix( - SVG.utils.map(source, function(n) { - return parseFloat(n) - }) - ) + // remove matrix wrapper and split to individual numbers + source = source + .replace(SVG.regex.whitespace, '') + .replace(SVG.regex.matrix, '') + .split(',') + + // convert string values to floats and convert to a matrix-formatted object + return arrayToMatrix( + SVG.utils.map(source, function(n) { + return parseFloat(n) + }) + ) } // Calculate position according to from and to function at(o, pos) { - // number recalculation (don't bother converting to SVG.Number for performance reasons) - return typeof o.from == 'number' ? - o.from + (o.to - o.from) * pos : - - // instance recalculation - o instanceof SVG.Color || o instanceof SVG.Number || o instanceof SVG.Matrix ? o.at(pos) : - - // for all other values wait until pos has reached 1 to return the final value - pos < 1 ? o.from : o.to + // number recalculation (don't bother converting to SVG.Number for performance reasons) + return typeof o.from == 'number' ? + o.from + (o.to - o.from) * pos : + + // instance recalculation + o instanceof SVG.Color || o instanceof SVG.Number || o instanceof SVG.Matrix ? o.at(pos) : + + // for all other values wait until pos has reached 1 to return the final value + pos < 1 ? o.from : o.to } // PathArray Helpers function arrayToString(a) { - for (var i = 0, il = a.length, s = ''; i < il; i++) { - s += a[i][0] - - if (a[i][1] != null) { - s += a[i][1] - - if (a[i][2] != null) { - s += ' ' - s += a[i][2] - - if (a[i][3] != null) { - s += ' ' - s += a[i][3] - s += ' ' - s += a[i][4] - - if (a[i][5] != null) { - s += ' ' - s += a[i][5] - s += ' ' - s += a[i][6] - - if (a[i][7] != null) { - s += ' ' - s += a[i][7] - } - } - } - } - } - } - - return s + ' ' + for (var i = 0, il = a.length, s = ''; i < il; i++) { + s += a[i][0] + + if (a[i][1] != null) { + s += a[i][1] + + if (a[i][2] != null) { + s += ' ' + s += a[i][2] + + if (a[i][3] != null) { + s += ' ' + s += a[i][3] + s += ' ' + s += a[i][4] + + if (a[i][5] != null) { + s += ' ' + s += a[i][5] + s += ' ' + s += a[i][6] + + if (a[i][7] != null) { + s += ' ' + s += a[i][7] + } + } + } + } + } + } + + return s + ' ' } // Deep new id assignment function assignNewId(node) { - // Do the same for SVG child nodes as well - for (var i = node.childNodes.length - 1; i >= 0; i--) - if (node.childNodes[i] instanceof SVGElement) - assignNewId(node.childNodes[i]) + // do the same for SVG child nodes as well + for (var i = node.childNodes.length - 1; i >= 0; i--) + if (node.childNodes[i] instanceof SVGElement) + assignNewId(node.childNodes[i]) - return SVG.adopt(node).id(SVG.eid(node.nodeName)) + return SVG.adopt(node).id(SVG.eid(node.nodeName)) } // Add more bounding box properties function fullBox(b) { - b.x2 = b.x + b.width - b.y2 = b.y + b.height - b.cx = b.x + b.width / 2 - b.cy = b.y + b.height / 2 - - return b + if (b.x == null) { + b.x = 0 + b.y = 0 + b.width = 0 + b.height = 0 + } + + b.w = b.width + b.h = b.height + b.x2 = b.x + b.width + b.y2 = b.y + b.height + b.cx = b.x + b.width / 2 + b.cy = b.y + b.height / 2 + + return b } // Get id from reference string function idFromReference(url) { - var m = url.toString().match(SVG.regex.reference) + var m = url.toString().match(SVG.regex.reference) - if (m) return m[1] + if (m) return m[1] } // Create matrix array for looping @@ -158,9 +167,9 @@ var abcdef = 'abcdef'.split('') // Shim layer with setTimeout fallback by Paul Irish window.requestAnimFrame = (function(){ - return window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.msRequestAnimationFrame || - function (c) { window.setTimeout(c, 1000 / 60) } + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.msRequestAnimationFrame || + function (c) { window.setTimeout(c, 1000 / 60) } })()
\ No newline at end of file diff --git a/src/matrix.js b/src/matrix.js index 7ee2874..26b7613 100644 --- a/src/matrix.js +++ b/src/matrix.js @@ -18,6 +18,9 @@ SVG.Matrix = SVG.invent({ this[abcdef[i]] = typeof source[abcdef[i]] === 'number' ? source[abcdef[i]] : base[abcdef[i]] + // merge polymertic values + if (source._r) + this._r = source._r } // Add methods @@ -52,6 +55,10 @@ SVG.Matrix = SVG.invent({ // store new destination this.destination = new SVG.Matrix(matrix) + // detect polymetric rotation + if (this.destination._r) + this._r = this.extract() + return this } // Get morphed matrix at a given position @@ -60,7 +67,7 @@ SVG.Matrix = SVG.invent({ if (!this.destination) return this // calculate morphed matrix at a given position - return new SVG.Matrix({ + var matrix = new SVG.Matrix({ a: this.a + (this.destination.a - this.a) * pos , b: this.b + (this.destination.b - this.b) * pos , c: this.c + (this.destination.c - this.c) * pos @@ -68,6 +75,16 @@ SVG.Matrix = SVG.invent({ , e: this.e + (this.destination.e - this.e) * pos , f: this.f + (this.destination.f - this.f) * pos }) + + // add polymetric rotation if required + if (this._r && this.destination._r) + matrix = matrix.rotate( + this._r.rotation + (this.destination._r.rotation - this._r.rotation) * pos + , this.destination._r.cx + , this.destination._r.cy + ) + + return matrix } // Multiplies by given matrix , multiply: function(matrix) { diff --git a/src/transform.js b/src/transform.js index da2bf37..c4f8f70 100644 --- a/src/transform.js +++ b/src/transform.js @@ -26,16 +26,21 @@ SVG.extend(SVG.Element, SVG.FX, { // absolute new SVG.Matrix(o) - // act on rotate + // act on rotation } else if (o.rotation != null) { o.cx = o.cx == null ? target.bbox().cx : o.cx o.cy = o.cy == null ? target.bbox().cy : o.cy - matrix = relative ? - // relative - target.attr('transform', matrix + ' rotate(' + [o.rotation, o.cx, o.cy].join() + ')').ctm() : - // absolute - matrix.rotate(o.rotation - matrix.extract().rotation, o.cx, o.cy) + if (this instanceof SVG.FX) { + o.rotation -= (relative ? 0 : matrix.extract().rotation) + matrix._r = o + } else { + matrix = relative ? + // relative + target.attr('transform', matrix + ' rotate(' + [o.rotation, o.cx, o.cy].join() + ')').ctm() : + // absolute + matrix.rotate(o.rotation - matrix.extract().rotation, o.cx, o.cy) + } // act on scale } else if (o.scale != null || o.scaleX != null || o.scaleY != null) { @@ -86,7 +91,7 @@ SVG.extend(SVG.Element, SVG.FX, { if (o.y != null) matrix.f = o.y } } - + return this.attr('transform', matrix) } }) |