1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
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
if (element) {
// Get current extracted transformations
var t = new SVG.Matrix(element).extract()
// Find native bbox
if (element.node.getBBox)
box = element.node.getBBox()
// Mimic bbox
else
box = {
x: element.node.clientLeft
, y: element.node.clientTop
, width: element.node.clientWidth
, height: element.node.clientHeight
}
// Include translations on x an y
this.x = box.x + t.x
this.y = box.y + t.y
// Plain width and height
this.width = box.width * t.scaleX
this.height = box.height * t.scaleY
}
// 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.RBox = SVG.invent({
// Initialize
create: function(element) {
var e, zoom
, box = {}
// Initialize zero box
this.x = 0
this.y = 0
this.width = 0
this.height = 0
if (element) {
e = element.doc().parent()
zoom = element.doc().viewbox().zoom
// Actual, native bounding box
box = element.node.getBoundingClientRect()
// 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
}
}
}
// Recalculate viewbox distortion
this.x /= zoom
this.y /= zoom
this.width = box.width /= zoom
this.height = box.height /= zoom
// 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
fullBox(this)
}
// define Parent
, parent: SVG.Element
// Constructor
, construct: {
// Get rect box
rbox: function() {
return new SVG.RBox(this)
}
}
})
// 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 box
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)
}
})
})
|