Reputation: 305
I have two flot charts and three data sets with crosshair in sync on both charts and dynamic legends that indicates value of each point on graph. Legend in the second chart does not show value where other two work fine. How would one make third or more legends show dynamic values as well. Moreover, can one make improvements to existing code where any number of charts with crosshair in sync can be displayed? Thanks,
Here is the fiddle: http://jsfiddle.net/mashinista/Q24qN/
and this is the code
plot = null;
plot2 = null;
var data1 = [
[gd(2012, 0, 1), 8],
[gd(2012, 1, 1), 13],
[gd(2012, 2, 1), 4],
[gd(2012, 3, 4), 8],
[gd(2012, 4, 1), 16],
[gd(2012, 5, 1), 20],
[gd(2012, 6, 1), 29],
[gd(2012, 7, 1), 23],
[gd(2012, 8, 1), 28],
[gd(2012, 9, 1), 16],
[gd(2012, 10, 1), 8],
[gd(2012, 11, 2), 4]
];
var data2 = [
[gd(2012, 0, 1), 16],
[gd(2012, 1, 1), 14],
[gd(2012, 2, 1), 22],
[gd(2012, 3, 1), 30],
[gd(2012, 4, 1), 28],
[gd(2012, 5, 1), 39],
[gd(2012, 6, 1), 38],
[gd(2012, 7, 1), 28],
[gd(2012, 8, 1), 31],
[gd(2012, 9, 1), 28],
[gd(2012, 10, 1), 22],
[gd(2012, 11, 1), 16]
];
var data3 = [
[gd(2012, 0, 1), 16],
[gd(2012, 1, 1), 14],
[gd(2012, 2, 1), 22],
[gd(2012, 3, 1), 30],
[gd(2012, 4, 1), 28],
[gd(2012, 5, 1), 39],
[gd(2012, 6, 1), 29],
[gd(2012, 7, 1), 23],
[gd(2012, 8, 1), 28],
[gd(2012, 9, 1), 16],
[gd(2012, 10, 1), 8],
[gd(2012, 11, 2), 4]
];
function gd(year, month, day) {
return new Date(year, month, day).getTime();
}
$(function () {
var sin = [], cos = [];
for (var i = 0; i < 14; i += 0.1) {
sin.push([i, Math.sin(i)]);
cos.push([i, Math.cos(i)]);
}
plot = $.plot($("#placeholder"),
[ { data: data1, label: "Query1 = 0.00"}, {
data: data2, label: "Query2 = 0.00"}],
{
series: {
lines: { show: true }
},
crosshair: { mode: "x" },
grid: { hoverable: true, autoHighlight: false},
yaxis: { min: 0, max: 40 },
xaxis: {mode: "time"}
});
plot2 = $.plot($("#placeholder2"),
[ { data: data3, label: "Query3 = 0.00"} ], {
series: {
lines: { show: true },
color: "#2eef34"
},
crosshair: { mode: "x" },
grid: { hoverable: true, autoHighlight: false},
yaxis: { min: 0, max: 40 },
xaxis: {mode: "time"}
});
var legends = $("#placeholder .legendLabel, #placeholder .legendLabel");
var updateLegendTimeout = null;
var latestPosition = null;
function updateLegend() {
updateLegendTimeout = null;
var pos = latestPosition;
var axes = plot.getAxes();
if (pos.x < axes.xaxis.min || pos.x > axes.xaxis.max || pos.y < axes.yaxis.min || pos.y > axes.yaxis.max) return;
var i, j, dataset = plot.getData();
for (i = 0; i < dataset.length; ++i) {
var series = dataset[i];
// find the nearest points, x-wise
for (j = 0; j < series.data.length; ++j)
if (series.data[j][0] > pos.x) break;
// now interpolate
var y, p1 = series.data[j - 1],
p2 = series.data[j];
if (p1 == null) y = p2[1];
else if (p2 == null) y = p1[1];
else y = p1[1] + (p2[1] - p1[1]) * (pos.x - p1[0]) / (p2[0] - p1[0]);
legends.eq(i).text(series.label.replace(/=.*/, "= " + y.toFixed(2) + " "));
}
}
$("#placeholder").bind("plothover", function (event, pos, item) {
plot2.setCrosshair({x: pos.x}),
latestPosition = pos;
if (!updateLegendTimeout) updateLegendTimeout = setTimeout(updateLegend, 50);
});
$("#placeholder2").bind("plothover", function (event, pos, item) {
plot.setCrosshair({x: pos.x}),
latestPosition = pos;
if (!updateLegendTimeout) updateLegendTimeout = setTimeout(updateLegend, 50);
});
});
Upvotes: 1
Views: 1391
Reputation: 17560
There were two errors which needed fixing:
1) Your legends array contains only the legends from the first plot:
var legends = $("#placeholder .legendLabel, #placeholder .legendLabel");
needs to be
var legends = $("#placeholder .legendLabel, #placeholder2 .legendLabel");
2) In your updateLegend
method you only use the data from the first plot:
var i, j, dataset = plot.getData();
I added a for
loop over both plots / datasets:
for (var p = 0; p <= 1; p++) {
var i, j, dataset;
if (p == 0) dataset = plot.getData();
else dataset = plot2.getData();
...
legends.eq(i + p * 2).text(series.label.replace(/=.*/, "= " + y.toFixed(2) + " "));
See this updated fiddle for the working code.
3) More charts:
If you want to add a larger number of charts then you need to change the same lines of code as above. For the dataset
you can use a switch
statement or build an array of flot
objects and then use something like
var dataset = plot[p].getData();
And for the legend number you have to count the number of legends / dataseries per chart:
legends.eq(i + countOfLegendsFromOtherCharts(p)).text( ... );
with something like this (but maybe better store this values somewhere):
function countOfLegendsFromOtherCharts(p) {
var count = 0;
for (var i = 0; i < p; i++) {
var dataset = plot[p].getData();
count += dataset.length;
}
return count;
}
Upvotes: 3