summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUlrich-Matthias Schäfer <ulima.ums@googlemail.com>2017-03-08 14:29:15 +0100
committerGitHub <noreply@github.com>2017-03-08 14:29:15 +0100
commit0534a6760a094d5a9425bde1d89bb8b71ae6a798 (patch)
tree2585c5ac4ec556626550499566cbcbefb68be24e /src
parent2fc62c55b889b0b533b17b2d4d9207f4b6c8b482 (diff)
downloadsvg.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.js160
-rw-r--r--src/matrix.js10
-rw-r--r--src/set.js14
-rw-r--r--src/transform.js4
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())
}
diff --git a/src/set.js b/src/set.js
index 41289dd..9da52c7 100644
--- a/src/set.js
+++ b/src/set.js
@@ -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))