diff options
author | Ulrich-Matthias Schäfer <ulima.ums@googlemail.com> | 2017-03-08 14:29:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-08 14:29:15 +0100 |
commit | 0534a6760a094d5a9425bde1d89bb8b71ae6a798 (patch) | |
tree | 2585c5ac4ec556626550499566cbcbefb68be24e /src | |
parent | 2fc62c55b889b0b533b17b2d4d9207f4b6c8b482 (diff) | |
download | svg.js-0534a6760a094d5a9425bde1d89bb8b71ae6a798.tar.gz svg.js-0534a6760a094d5a9425bde1d89bb8b71ae6a798.zip |
added SVG.Box, added transform method to boxes, fix rbox (#626)
added SVG.Box, added transform method to boxes, fix rbox
Also:
- workaround for screenCTM with nested svg (FF bug)
- remove unneeded workaround in toParent()
- rbox accepts additional parameter to transform the box
Diffstat (limited to 'src')
-rw-r--r-- | src/boxes.js | 160 | ||||
-rw-r--r-- | src/matrix.js | 10 | ||||
-rw-r--r-- | src/set.js | 14 | ||||
-rw-r--r-- | src/transform.js | 4 |
4 files changed, 105 insertions, 83 deletions
diff --git a/src/boxes.js b/src/boxes.js index 4198ea1..9d2ef04 100644 --- a/src/boxes.js +++ b/src/boxes.js @@ -1,8 +1,71 @@ +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 || x.x, 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) { + 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 @@ -28,19 +91,14 @@ SVG.BBox = SVG.invent({ } } - // plain x and y - this.x = box.x - this.y = box.y - - // plain width and height - this.width = box.width - this.height = box.height + SVG.Box.call(this, box) } - // add center, right and bottom - fullBox(this) } + // Define ancestor +, inherit: SVG.Box + // Define Parent , parent: SVG.Element @@ -54,87 +112,49 @@ SVG.BBox = SVG.invent({ }) +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() + return this.rbox(this.doc()) } }) SVG.RBox = SVG.invent({ // Initialize create: function(element) { - if (element) { - var e = element.doc().parent() - , box = element.node.getBoundingClientRect() - , zoom = 1 - - // get screen offset - this.x = box.left - this.y = box.top - - // subtract parent offset - this.x -= e.offsetLeft - this.y -= e.offsetTop - - while (e = e.offsetParent) { - this.x -= e.offsetLeft - this.y -= e.offsetTop - } - - // calculate cumulative zoom from svg documents - e = element - while (e.parent && (e = e.parent())) { - if (e.viewbox) { - zoom *= e.viewbox().zoom - this.x -= e.x() || 0 - this.y -= e.y() || 0 - } - } + SVG.Box.apply(this, [].slice.call(arguments)) - // recalculate viewbox distortion - this.width = box.width /= zoom - this.height = box.height /= zoom + if (element instanceof SVG.Element) { + SVG.Box.call(this, element.node.getBoundingClientRect()) } - - // add center, right and bottom - fullBox(this) - - // offset by window scroll position, because getBoundingClientRect changes when window is scrolled - this.x += window.pageXOffset - this.y += window.pageYOffset } +, 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() { - return new SVG.RBox(this) + rbox: function(el) { + if (el) return new SVG.RBox(this).transform(el.screenCTM().inverse()) + return new SVG.RBox(this).addOffset() } } }) -// Add universal merge method -;[SVG.BBox, 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 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) - } - - }) - -}) +SVG.RBox.prototype.constructor = SVG.RBox diff --git a/src/matrix.js b/src/matrix.js index c040b7a..60f3531 100644 --- a/src/matrix.js +++ b/src/matrix.js @@ -182,6 +182,16 @@ SVG.Matrix = SVG.invent({ }, // Get current screen matrix screenCTM: function() { + /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 + This is needed because FF does not return the transformation matrix + for the inner coordinate system when getScreenCTM() is called on nested svgs. + However all other Browsers do that */ + if(this instanceof SVG.Nested) { + var rect = this.rect(1,1) + var m = rect.node.getScreenCTM() + rect.remove() + return new SVG.Matrix(m) + } return new SVG.Matrix(this.node.getScreenCTM()) } @@ -70,25 +70,19 @@ SVG.Set = SVG.invent({ } // Get the bounding box of all members included or empty box if set has no items , bbox: function(){ - var box = new SVG.BBox() - // return an empty box of there are no members if (this.members.length == 0) - return box + return new SVG.RBox() // get the first rbox and update the target bbox - var rbox = this.members[0].rbox() - box.x = rbox.x - box.y = rbox.y - box.width = rbox.width - box.height = rbox.height + var rbox = this.members[0].rbox(this.members[0].doc()) this.each(function() { // user rbox for correct position and visual representation - box = box.merge(this.rbox()) + rbox = rbox.merge(this.rbox(this.doc())) }) - return box + return rbox } } diff --git a/src/transform.js b/src/transform.js index e686ce4..d1db74a 100644 --- a/src/transform.js +++ b/src/transform.js @@ -201,9 +201,7 @@ SVG.extend(SVG.Element, { toParent: function(parent) { if(this == parent) return this var ctm = this.screenCTM() - var temp = parent.rect(1,1) - var pCtm = temp.screenCTM().inverse() - temp.remove() + var pCtm = parent.screenCTM().inverse() this.addTo(parent).untransform().transform(pCtm.multiply(ctm)) |