You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			227 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
			
		
		
	
	
			227 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
/* Flot plugin for computing bottoms for filled line and bar charts.
 | 
						|
 | 
						|
Copyright (c) 2007-2014 IOLA and Ole Laursen.
 | 
						|
Licensed under the MIT license.
 | 
						|
 | 
						|
The case: you've got two series that you want to fill the area between. In Flot
 | 
						|
terms, you need to use one as the fill bottom of the other. You can specify the
 | 
						|
bottom of each data point as the third coordinate manually, or you can use this
 | 
						|
plugin to compute it for you.
 | 
						|
 | 
						|
In order to name the other series, you need to give it an id, like this:
 | 
						|
 | 
						|
	var dataset = [
 | 
						|
		{ data: [ ... ], id: "foo" } ,         // use default bottom
 | 
						|
		{ data: [ ... ], fillBetween: "foo" }, // use first dataset as bottom
 | 
						|
	];
 | 
						|
 | 
						|
	$.plot($("#placeholder"), dataset, { lines: { show: true, fill: true }});
 | 
						|
 | 
						|
As a convenience, if the id given is a number that doesn't appear as an id in
 | 
						|
the series, it is interpreted as the index in the array instead (so fillBetween:
 | 
						|
0 can also mean the first series).
 | 
						|
 | 
						|
Internally, the plugin modifies the datapoints in each series. For line series,
 | 
						|
extra data points might be inserted through interpolation. Note that at points
 | 
						|
where the bottom line is not defined (due to a null point or start/end of line),
 | 
						|
the current line will show a gap too. The algorithm comes from the
 | 
						|
jquery.flot.stack.js plugin, possibly some code could be shared.
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
(function ( $ ) {
 | 
						|
 | 
						|
	var options = {
 | 
						|
		series: {
 | 
						|
			fillBetween: null	// or number
 | 
						|
		}
 | 
						|
	};
 | 
						|
 | 
						|
	function init( plot ) {
 | 
						|
 | 
						|
		function findBottomSeries( s, allseries ) {
 | 
						|
 | 
						|
			var i;
 | 
						|
 | 
						|
			for ( i = 0; i < allseries.length; ++i ) {
 | 
						|
				if ( allseries[ i ].id === s.fillBetween ) {
 | 
						|
					return allseries[ i ];
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if ( typeof s.fillBetween === "number" ) {
 | 
						|
				if ( s.fillBetween < 0 || s.fillBetween >= allseries.length ) {
 | 
						|
					return null;
 | 
						|
				}
 | 
						|
				return allseries[ s.fillBetween ];
 | 
						|
			}
 | 
						|
 | 
						|
			return null;
 | 
						|
		}
 | 
						|
 | 
						|
		function computeFillBottoms( plot, s, datapoints ) {
 | 
						|
 | 
						|
			if ( s.fillBetween == null ) {
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			var other = findBottomSeries( s, plot.getData() );
 | 
						|
 | 
						|
			if ( !other ) {
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			var ps = datapoints.pointsize,
 | 
						|
				points = datapoints.points,
 | 
						|
				otherps = other.datapoints.pointsize,
 | 
						|
				otherpoints = other.datapoints.points,
 | 
						|
				newpoints = [],
 | 
						|
				px, py, intery, qx, qy, bottom,
 | 
						|
				withlines = s.lines.show,
 | 
						|
				withbottom = ps > 2 && datapoints.format[2].y,
 | 
						|
				withsteps = withlines && s.lines.steps,
 | 
						|
				fromgap = true,
 | 
						|
				i = 0,
 | 
						|
				j = 0,
 | 
						|
				l, m;
 | 
						|
 | 
						|
			while ( true ) {
 | 
						|
 | 
						|
				if ( i >= points.length ) {
 | 
						|
					break;
 | 
						|
				}
 | 
						|
 | 
						|
				l = newpoints.length;
 | 
						|
 | 
						|
				if ( points[ i ] == null ) {
 | 
						|
 | 
						|
					// copy gaps
 | 
						|
 | 
						|
					for ( m = 0; m < ps; ++m ) {
 | 
						|
						newpoints.push( points[ i + m ] );
 | 
						|
					}
 | 
						|
 | 
						|
					i += ps;
 | 
						|
 | 
						|
				} else if ( j >= otherpoints.length ) {
 | 
						|
 | 
						|
					// for lines, we can't use the rest of the points
 | 
						|
 | 
						|
					if ( !withlines ) {
 | 
						|
						for ( m = 0; m < ps; ++m ) {
 | 
						|
							newpoints.push( points[ i + m ] );
 | 
						|
						}
 | 
						|
					}
 | 
						|
 | 
						|
					i += ps;
 | 
						|
 | 
						|
				} else if ( otherpoints[ j ] == null ) {
 | 
						|
 | 
						|
					// oops, got a gap
 | 
						|
 | 
						|
					for ( m = 0; m < ps; ++m ) {
 | 
						|
						newpoints.push( null );
 | 
						|
					}
 | 
						|
 | 
						|
					fromgap = true;
 | 
						|
					j += otherps;
 | 
						|
 | 
						|
				} else {
 | 
						|
 | 
						|
					// cases where we actually got two points
 | 
						|
 | 
						|
					px = points[ i ];
 | 
						|
					py = points[ i + 1 ];
 | 
						|
					qx = otherpoints[ j ];
 | 
						|
					qy = otherpoints[ j + 1 ];
 | 
						|
					bottom = 0;
 | 
						|
 | 
						|
					if ( px === qx ) {
 | 
						|
 | 
						|
						for ( m = 0; m < ps; ++m ) {
 | 
						|
							newpoints.push( points[ i + m ] );
 | 
						|
						}
 | 
						|
 | 
						|
						//newpoints[ l + 1 ] += qy;
 | 
						|
						bottom = qy;
 | 
						|
 | 
						|
						i += ps;
 | 
						|
						j += otherps;
 | 
						|
 | 
						|
					} else if ( px > qx ) {
 | 
						|
 | 
						|
						// we got past point below, might need to
 | 
						|
						// insert interpolated extra point
 | 
						|
 | 
						|
						if ( withlines && i > 0 && points[ i - ps ] != null ) {
 | 
						|
							intery = py + ( points[ i - ps + 1 ] - py ) * ( qx - px ) / ( points[ i - ps ] - px );
 | 
						|
							newpoints.push( qx );
 | 
						|
							newpoints.push( intery );
 | 
						|
							for ( m = 2; m < ps; ++m ) {
 | 
						|
								newpoints.push( points[ i + m ] );
 | 
						|
							}
 | 
						|
							bottom = qy;
 | 
						|
						}
 | 
						|
 | 
						|
						j += otherps;
 | 
						|
 | 
						|
					} else { // px < qx
 | 
						|
 | 
						|
						// if we come from a gap, we just skip this point
 | 
						|
 | 
						|
						if ( fromgap && withlines ) {
 | 
						|
							i += ps;
 | 
						|
							continue;
 | 
						|
						}
 | 
						|
 | 
						|
						for ( m = 0; m < ps; ++m ) {
 | 
						|
							newpoints.push( points[ i + m ] );
 | 
						|
						}
 | 
						|
 | 
						|
						// we might be able to interpolate a point below,
 | 
						|
						// this can give us a better y
 | 
						|
 | 
						|
						if ( withlines && j > 0 && otherpoints[ j - otherps ] != null ) {
 | 
						|
							bottom = qy + ( otherpoints[ j - otherps + 1 ] - qy ) * ( px - qx ) / ( otherpoints[ j - otherps ] - qx );
 | 
						|
						}
 | 
						|
 | 
						|
						//newpoints[l + 1] += bottom;
 | 
						|
 | 
						|
						i += ps;
 | 
						|
					}
 | 
						|
 | 
						|
					fromgap = false;
 | 
						|
 | 
						|
					if ( l !== newpoints.length && withbottom ) {
 | 
						|
						newpoints[ l + 2 ] = bottom;
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
				// maintain the line steps invariant
 | 
						|
 | 
						|
				if ( withsteps && l !== newpoints.length && l > 0 &&
 | 
						|
					newpoints[ l ] !== null &&
 | 
						|
					newpoints[ l ] !== newpoints[ l - ps ] &&
 | 
						|
					newpoints[ l + 1 ] !== newpoints[ l - ps + 1 ] ) {
 | 
						|
					for (m = 0; m < ps; ++m) {
 | 
						|
						newpoints[ l + ps + m ] = newpoints[ l + m ];
 | 
						|
					}
 | 
						|
					newpoints[ l + 1 ] = newpoints[ l - ps + 1 ];
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			datapoints.points = newpoints;
 | 
						|
		}
 | 
						|
 | 
						|
		plot.hooks.processDatapoints.push( computeFillBottoms );
 | 
						|
	}
 | 
						|
 | 
						|
	$.plot.plugins.push({
 | 
						|
		init: init,
 | 
						|
		options: options,
 | 
						|
		name: "fillbetween",
 | 
						|
		version: "1.0"
 | 
						|
	});
 | 
						|
 | 
						|
})(jQuery);
 |