169 lines
4.3 KiB
JavaScript
169 lines
4.3 KiB
JavaScript
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, bbox
|
|
|
|
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 pain 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.instance).show()
|
|
box = clone.node.getBBox()
|
|
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
|