Commit 7a665a14 authored by olau@iola.dk's avatar olau@iola.dk

Added support for line segments and null/NaN values

git-svn-id: https://flot.googlecode.com/svn/trunk@51 1e0a6537-2640-0410-bfb7-f154510ff394
parent bedf4fb2
...@@ -16,8 +16,8 @@ options. The "plot" object returned has some members you can call. ...@@ -16,8 +16,8 @@ options. The "plot" object returned has some members you can call.
These are documented separately below. These are documented separately below.
Note that in general Flot gives no guarantees if you change any of the Note that in general Flot gives no guarantees if you change any of the
objects you pass in to the plot function or get out of it. The objects objects you pass in to the plot function or get out of it since
may not be deep-copied. they're not necessarily deep-copied.
Data Format Data Format
...@@ -38,10 +38,14 @@ E.g. ...@@ -38,10 +38,14 @@ E.g.
Note that to simplify the internal logic in Flot both the x and y Note that to simplify the internal logic in Flot both the x and y
values must be numbers, even if specifying time series (see below for values must be numbers, even if specifying time series (see below for
how to do this). If you put in something else, e.g. a string, the plot how to do this). This is a common problem because you might
function fails with strange errors. This is a common problem because accidentally retrieve data from the database as strings and serialize
you might accidentally retrieve data from the database as strings and them directly to JSON without noticing the wrong type.
serialize them directly to JSON without noticing the wrong type.
If a null is specified as a point or if one of the coordinates is null
or NaN, the point is ignored. As a special case, a null value for
lines is interpreted as a line segment end, i.e. the two points before
and after the null value are not connected.
The format of a single series object is as follows: The format of a single series object is as follows:
......
...@@ -34,9 +34,6 @@ interactive hover over ...@@ -34,9 +34,6 @@ interactive hover over
- fire event with value for points - fire event with value for points
- fire event with graph id for lines - fire event with graph id for lines
support segmented lines
- put in null value to signify a break in the data set
error margin indicators error margin indicators
- for scientific/statistical purposes - for scientific/statistical purposes
......
...@@ -27,7 +27,10 @@ $(function () { ...@@ -27,7 +27,10 @@ $(function () {
var d2 = [[0, 3], [4, 8], [8, 5], [9, 13]]; var d2 = [[0, 3], [4, 8], [8, 5], [9, 13]];
$.plot($("#placeholder"), [ d1, d2 ]); // a null signifies separate line segments
var d3 = [[0, 12], [7, 12], null, [7, 2.5], [12, 2.5]];
$.plot($("#placeholder"), [ d1, d2, d3 ]);
}); });
</script> </script>
......
...@@ -200,11 +200,12 @@ ...@@ -200,11 +200,12 @@
if (data[j] == null) if (data[j] == null)
continue; continue;
var x = data[j][0]; var x = data[j][0], y = data[j][1];
var y = data[j][1];
if (x == null || isNaN(x) || y == null || isNaN(y)) if (x == null || isNaN(x) || y == null || isNaN(y)) {
data[j] = null; // mark this point as invalid
continue; continue;
}
if (x < xaxis.datamin) if (x < xaxis.datamin)
xaxis.datamin = x; xaxis.datamin = x;
...@@ -841,17 +842,18 @@ ...@@ -841,17 +842,18 @@
function drawSeriesLines(series) { function drawSeriesLines(series) {
function plotLine(data, offset) { function plotLine(data, offset) {
if (data.length < 2) var prev, cur = null, drawx = null, drawy = null;
return;
var prevx = tHoz(data[0][0]),
prevy = tVert(data[0][1]) + offset;
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(prevx, prevy); for (var i = 0; i < data.length; ++i) {
for (var i = 0; i < data.length - 1; ++i) { prev = cur;
var x1 = data[i][0], y1 = data[i][1], cur = data[i];
x2 = data[i+1][0], y2 = data[i+1][1];
if (prev == null || cur == null)
continue;
var x1 = prev[0], y1 = prev[1],
x2 = cur[0], y2 = cur[1];
// clip with ymin // clip with ymin
if (y1 <= y2 && y1 < yaxis.min) { if (y1 <= y2 && y1 < yaxis.min) {
...@@ -910,29 +912,41 @@ ...@@ -910,29 +912,41 @@
x2 = xaxis.max; x2 = xaxis.max;
} }
if (prevx != tHoz(x1) || prevy != tVert(y1) + offset) if (drawx != tHoz(x1) || drawy != tVert(y1) + offset)
ctx.moveTo(tHoz(x1), tVert(y1) + offset); ctx.moveTo(tHoz(x1), tVert(y1) + offset);
prevx = tHoz(x2); drawx = tHoz(x2);
prevy = tVert(y2) + offset; drawy = tVert(y2) + offset;
ctx.lineTo(prevx, prevy); ctx.lineTo(drawx, drawy);
} }
ctx.stroke(); ctx.stroke();
} }
function plotLineArea(data) { function plotLineArea(data) {
if (data.length < 2) var prev, cur = null;
return;
var bottom = Math.min(Math.max(0, yaxis.min), yaxis.max); var bottom = Math.min(Math.max(0, yaxis.min), yaxis.max);
var top, lastX = 0; var top, lastX = 0;
var first = true; var areaOpen = false;
ctx.beginPath(); for (var i = 0; i < data.length; ++i) {
for (var i = 0; i < data.length - 1; ++i) { prev = cur;
var x1 = data[i][0], y1 = data[i][1], cur = data[i];
x2 = data[i+1][0], y2 = data[i+1][1];
if (areaOpen && prev != null && cur == null) {
// close area
ctx.lineTo(tHoz(lastX), tVert(bottom));
ctx.fill();
areaOpen = false;
continue;
}
if (prev == null || cur == null)
continue;
var x1 = prev[0], y1 = prev[1],
x2 = cur[0], y2 = cur[1];
// clip x values // clip x values
...@@ -964,9 +978,11 @@ ...@@ -964,9 +978,11 @@
x2 = xaxis.max; x2 = xaxis.max;
} }
if (first) { if (!areaOpen) {
// open area
ctx.beginPath();
ctx.moveTo(tHoz(x1), tVert(bottom)); ctx.moveTo(tHoz(x1), tVert(bottom));
first = false; areaOpen = true;
} }
// now first check the case where both is outside // now first check the case where both is outside
...@@ -1038,16 +1054,12 @@ ...@@ -1038,16 +1054,12 @@
lastX = Math.max(x2, x2old); lastX = Math.max(x2, x2old);
} }
/*
ctx.beginPath(); if (areaOpen) {
ctx.moveTo(tHoz(data[0][0]), tVert(0));
for (var i = 0; i < data.length; i++) {
ctx.lineTo(tHoz(data[i][0]), tVert(data[i][1]));
}
ctx.lineTo(tHoz(data[data.length - 1][0]), tVert(0));*/
ctx.lineTo(tHoz(lastX), tVert(bottom)); ctx.lineTo(tHoz(lastX), tVert(bottom));
ctx.fill(); ctx.fill();
} }
}
ctx.save(); ctx.save();
ctx.translate(plotOffset.left, plotOffset.top); ctx.translate(plotOffset.left, plotOffset.top);
...@@ -1081,6 +1093,9 @@ ...@@ -1081,6 +1093,9 @@
function drawSeriesPoints(series) { function drawSeriesPoints(series) {
function plotPoints(data, radius, fill) { function plotPoints(data, radius, fill) {
for (var i = 0; i < data.length; ++i) { for (var i = 0; i < data.length; ++i) {
if (data[i] == null)
continue;
var x = data[i][0], y = data[i][1]; var x = data[i][0], y = data[i][1];
if (x < xaxis.min || x > xaxis.max || y < yaxis.min || y > yaxis.max) if (x < xaxis.min || x > xaxis.max || y < yaxis.min || y > yaxis.max)
continue; continue;
...@@ -1095,6 +1110,9 @@ ...@@ -1095,6 +1110,9 @@
function plotPointShadows(data, offset, radius) { function plotPointShadows(data, offset, radius) {
for (var i = 0; i < data.length; ++i) { for (var i = 0; i < data.length; ++i) {
if (data[i] == null)
continue;
var x = data[i][0], y = data[i][1]; var x = data[i][0], y = data[i][1];
if (x < xaxis.min || x > xaxis.max || y < yaxis.min || y > yaxis.max) if (x < xaxis.min || x > xaxis.max || y < yaxis.min || y > yaxis.max)
continue; continue;
...@@ -1129,10 +1147,10 @@ ...@@ -1129,10 +1147,10 @@
function drawSeriesBars(series) { function drawSeriesBars(series) {
function plotBars(data, barWidth, offset, fill) { function plotBars(data, barWidth, offset, fill) {
if (data.length < 1)
return;
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
if (data[i] == null)
continue;
var x = data[i][0], y = data[i][1]; var x = data[i][0], y = data[i][1];
var drawLeft = true, drawTop = true, drawRight = true; var drawLeft = true, drawTop = true, drawRight = true;
var left = x, right = x + barWidth, bottom = 0, top = y; var left = x, right = x + barWidth, bottom = 0, top = y;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment