Subversion-Projekte lars-tiefland.ci

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
776 lars 1
/* Flot plugin for computing bottoms for filled line and bar charts.
2
 
3
Copyright (c) 2007-2014 IOLA and Ole Laursen.
4
Licensed under the MIT license.
5
 
6
The case: you've got two series that you want to fill the area between. In Flot
7
terms, you need to use one as the fill bottom of the other. You can specify the
8
bottom of each data point as the third coordinate manually, or you can use this
9
plugin to compute it for you.
10
 
11
In order to name the other series, you need to give it an id, like this:
12
 
13
	var dataset = [
14
		{ data: [ ... ], id: "foo" } ,         // use default bottom
15
		{ data: [ ... ], fillBetween: "foo" }, // use first dataset as bottom
16
	];
17
 
18
	$.plot($("#placeholder"), dataset, { lines: { show: true, fill: true }});
19
 
20
As a convenience, if the id given is a number that doesn't appear as an id in
21
the series, it is interpreted as the index in the array instead (so fillBetween:
22
 
23
 
24
Internally, the plugin modifies the datapoints in each series. For line series,
25
extra data points might be inserted through interpolation. Note that at points
26
where the bottom line is not defined (due to a null point or start/end of line),
27
the current line will show a gap too. The algorithm comes from the
28
jquery.flot.stack.js plugin, possibly some code could be shared.
29
 
30
*/
31
 
32
(function ( $ ) {
33
 
34
	var options = {
35
		series: {
36
			fillBetween: null	// or number
37
		}
38
	};
39
 
40
	function init( plot ) {
41
 
42
		function findBottomSeries( s, allseries ) {
43
 
44
			var i;
45
 
46
			for ( i = 0; i < allseries.length; ++i ) {
47
				if ( allseries[ i ].id === s.fillBetween ) {
48
					return allseries[ i ];
49
				}
50
			}
51
 
52
			if ( typeof s.fillBetween === "number" ) {
53
				if ( s.fillBetween < 0 || s.fillBetween >= allseries.length ) {
54
					return null;
55
				}
56
				return allseries[ s.fillBetween ];
57
			}
58
 
59
			return null;
60
		}
61
 
62
		function computeFillBottoms( plot, s, datapoints ) {
63
 
64
			if ( s.fillBetween == null ) {
65
				return;
66
			}
67
 
68
			var other = findBottomSeries( s, plot.getData() );
69
 
70
			if ( !other ) {
71
				return;
72
			}
73
 
74
			var ps = datapoints.pointsize,
75
				points = datapoints.points,
76
				otherps = other.datapoints.pointsize,
77
				otherpoints = other.datapoints.points,
78
				newpoints = [],
79
				px, py, intery, qx, qy, bottom,
80
				withlines = s.lines.show,
81
				withbottom = ps > 2 && datapoints.format[2].y,
82
				withsteps = withlines && s.lines.steps,
83
				fromgap = true,
84
				i = 0,
85
				j = 0,
86
				l, m;
87
 
88
			while ( true ) {
89
 
90
				if ( i >= points.length ) {
91
					break;
92
				}
93
 
94
				l = newpoints.length;
95
 
96
				if ( points[ i ] == null ) {
97
 
98
					// copy gaps
99
 
100
					for ( m = 0; m < ps; ++m ) {
101
						newpoints.push( points[ i + m ] );
102
					}
103
 
104
					i += ps;
105
 
106
				} else if ( j >= otherpoints.length ) {
107
 
108
					// for lines, we can't use the rest of the points
109
 
110
					if ( !withlines ) {
111
						for ( m = 0; m < ps; ++m ) {
112
							newpoints.push( points[ i + m ] );
113
						}
114
					}
115
 
116
					i += ps;
117
 
118
				} else if ( otherpoints[ j ] == null ) {
119
 
120
					// oops, got a gap
121
 
122
					for ( m = 0; m < ps; ++m ) {
123
						newpoints.push( null );
124
					}
125
 
126
					fromgap = true;
127
					j += otherps;
128
 
129
				} else {
130
 
131
					// cases where we actually got two points
132
 
133
					px = points[ i ];
134
					py = points[ i + 1 ];
135
					qx = otherpoints[ j ];
136
					qy = otherpoints[ j + 1 ];
137
					bottom = 0;
138
 
139
					if ( px === qx ) {
140
 
141
						for ( m = 0; m < ps; ++m ) {
142
							newpoints.push( points[ i + m ] );
143
						}
144
 
145
						//newpoints[ l + 1 ] += qy;
146
						bottom = qy;
147
 
148
						i += ps;
149
						j += otherps;
150
 
151
					} else if ( px > qx ) {
152
 
153
						// we got past point below, might need to
154
						// insert interpolated extra point
155
 
156
						if ( withlines && i > 0 && points[ i - ps ] != null ) {
157
							intery = py + ( points[ i - ps + 1 ] - py ) * ( qx - px ) / ( points[ i - ps ] - px );
158
							newpoints.push( qx );
159
							newpoints.push( intery );
160
							for ( m = 2; m < ps; ++m ) {
161
								newpoints.push( points[ i + m ] );
162
							}
163
							bottom = qy;
164
						}
165
 
166
						j += otherps;
167
 
168
					} else { // px < qx
169
 
170
						// if we come from a gap, we just skip this point
171
 
172
						if ( fromgap && withlines ) {
173
							i += ps;
174
							continue;
175
						}
176
 
177
						for ( m = 0; m < ps; ++m ) {
178
							newpoints.push( points[ i + m ] );
179
						}
180
 
181
						// we might be able to interpolate a point below,
182
						// this can give us a better y
183
 
184
						if ( withlines && j > 0 && otherpoints[ j - otherps ] != null ) {
185
							bottom = qy + ( otherpoints[ j - otherps + 1 ] - qy ) * ( px - qx ) / ( otherpoints[ j - otherps ] - qx );
186
						}
187
 
188
						//newpoints[l + 1] += bottom;
189
 
190
						i += ps;
191
					}
192
 
193
					fromgap = false;
194
 
195
					if ( l !== newpoints.length && withbottom ) {
196
						newpoints[ l + 2 ] = bottom;
197
					}
198
				}
199
 
200
				// maintain the line steps invariant
201
 
202
				if ( withsteps && l !== newpoints.length && l > 0 &&
203
					newpoints[ l ] !== null &&
204
					newpoints[ l ] !== newpoints[ l - ps ] &&
205
					newpoints[ l + 1 ] !== newpoints[ l - ps + 1 ] ) {
206
					for (m = 0; m < ps; ++m) {
207
						newpoints[ l + ps + m ] = newpoints[ l + m ];
208
					}
209
					newpoints[ l + 1 ] = newpoints[ l - ps + 1 ];
210
				}
211
			}
212
 
213
			datapoints.points = newpoints;
214
		}
215
 
216
		plot.hooks.processDatapoints.push( computeFillBottoms );
217
	}
218
 
219
	$.plot.plugins.push({
220
		init: init,
221
		options: options,
222
		name: "fillbetween",
223
		version: "1.0"
224
	});
225
 
226
})(jQuery);