root / hci / trunk / eneraptor-web-app / web-app / js / flot / jquery.flot.stack.js @ 69
History | View | Annotate | Download (5.33 KB)
1 |
/*
|
---|---|
2 |
Flot plugin for stacking data sets, i.e. putting them on top of each
|
3 |
other, for accumulative graphs. Note that the plugin assumes the data
|
4 |
is sorted on x. Also note that stacking a mix of positive and negative
|
5 |
values in most instances doesn't make sense (so it looks weird).
|
6 |
|
7 |
Two or more series are stacked when their "stack" attribute is set to
|
8 |
the same key (which can be any number or string or just "true"). To
|
9 |
specify the default stack, you can set
|
10 |
|
11 |
series: {
|
12 |
stack: null or true or key (number/string)
|
13 |
}
|
14 |
|
15 |
or specify it for a specific series
|
16 |
|
17 |
$.plot($("#placeholder"), [{ data: [ ... ], stack: true ])
|
18 |
|
19 |
The stacking order is determined by the order of the data series in
|
20 |
the array (later series end up on top of the previous).
|
21 |
|
22 |
Internally, the plugin modifies the datapoints in each series, adding
|
23 |
an offset to the y value. For line series, extra data points are
|
24 |
inserted through interpolation. For bar charts, the second y value is
|
25 |
also adjusted.
|
26 |
*/
|
27 |
|
28 |
(function ($) { |
29 |
var options = {
|
30 |
series: { stack: null } // or number/string |
31 |
}; |
32 |
|
33 |
function init(plot) { |
34 |
function findMatchingSeries(s, allseries) { |
35 |
var res = null |
36 |
for (var i = 0; i < allseries.length; ++i) { |
37 |
if (s == allseries[i])
|
38 |
break;
|
39 |
|
40 |
if (allseries[i].stack == s.stack)
|
41 |
res = allseries[i]; |
42 |
} |
43 |
|
44 |
return res;
|
45 |
} |
46 |
|
47 |
function stackData(plot, s, datapoints) { |
48 |
if (s.stack == null) |
49 |
return;
|
50 |
|
51 |
var other = findMatchingSeries(s, plot.getData());
|
52 |
if (!other)
|
53 |
return;
|
54 |
|
55 |
var ps = datapoints.pointsize,
|
56 |
points = datapoints.points, |
57 |
otherps = other.datapoints.pointsize, |
58 |
otherpoints = other.datapoints.points, |
59 |
newpoints = [], |
60 |
px, py, intery, qx, qy, bottom, |
61 |
withlines = s.lines.show, withbars = s.bars.show, |
62 |
withsteps = withlines && s.lines.steps, |
63 |
i = 0, j = 0, l; |
64 |
|
65 |
while (true) { |
66 |
if (i >= points.length)
|
67 |
break;
|
68 |
|
69 |
l = newpoints.length; |
70 |
|
71 |
if (j >= otherpoints.length
|
72 |
|| otherpoints[j] == null
|
73 |
|| points[i] == null) {
|
74 |
// degenerate cases
|
75 |
for (m = 0; m < ps; ++m) |
76 |
newpoints.push(points[i + m]); |
77 |
i += ps; |
78 |
} |
79 |
else {
|
80 |
// cases where we actually got two points
|
81 |
px = points[i]; |
82 |
py = points[i + 1];
|
83 |
qx = otherpoints[j]; |
84 |
qy = otherpoints[j + 1];
|
85 |
bottom = 0;
|
86 |
|
87 |
if (px == qx) {
|
88 |
for (m = 0; m < ps; ++m) |
89 |
newpoints.push(points[i + m]); |
90 |
|
91 |
newpoints[l + 1] += qy;
|
92 |
bottom = qy; |
93 |
|
94 |
i += ps; |
95 |
j += otherps; |
96 |
} |
97 |
else if (px > qx) { |
98 |
// we got past point below, might need to
|
99 |
// insert interpolated extra point
|
100 |
if (withlines && i > 0 && points[i - ps] != null) { |
101 |
intery = py + (points[i - ps + 1] - py) * (qx - px) / (points[i - ps] - px);
|
102 |
newpoints.push(qx); |
103 |
newpoints.push(intery + qy) |
104 |
for (m = 2; m < ps; ++m) |
105 |
newpoints.push(points[i + m]); |
106 |
bottom = qy; |
107 |
} |
108 |
|
109 |
j += otherps; |
110 |
} |
111 |
else {
|
112 |
for (m = 0; m < ps; ++m) |
113 |
newpoints.push(points[i + m]); |
114 |
|
115 |
// we might be able to interpolate a point below,
|
116 |
// this can give us a better y
|
117 |
if (withlines && j > 0 && otherpoints[j - ps] != null) |
118 |
bottom = qy + (otherpoints[j - ps + 1] - qy) * (px - qx) / (otherpoints[j - ps] - qx);
|
119 |
|
120 |
newpoints[l + 1] += bottom;
|
121 |
|
122 |
i += ps; |
123 |
} |
124 |
|
125 |
if (l != newpoints.length && withbars)
|
126 |
newpoints[l + 2] += bottom;
|
127 |
} |
128 |
|
129 |
// maintain the line steps invariant
|
130 |
if (withsteps && l != newpoints.length && l > 0 |
131 |
&& newpoints[l] != null
|
132 |
&& newpoints[l] != newpoints[l - ps] |
133 |
&& newpoints[l + 1] != newpoints[l - ps + 1]) { |
134 |
for (m = 0; m < ps; ++m) |
135 |
newpoints[l + ps + m] = newpoints[l + m]; |
136 |
newpoints[l + 1] = newpoints[l - ps + 1]; |
137 |
} |
138 |
} |
139 |
|
140 |
datapoints.points = newpoints; |
141 |
} |
142 |
|
143 |
plot.hooks.processDatapoints.push(stackData); |
144 |
} |
145 |
|
146 |
$.plot.plugins.push({
|
147 |
init: init,
|
148 |
options: options,
|
149 |
name: 'stack', |
150 |
version: '1.0' |
151 |
}); |
152 |
})(jQuery); |