cycero
cycero

Reputation: 4771

Get crosshair values across multiple Flot Charts

I'm using the jQuery Flot Charts plugin in one of my projects. I have several charts standing in the same column and what I'm trying to do is: Show the crosshair on all of the charts if you hover on any of them. I'm doing this successfully using the following code.

//graphs - this is an object which contains the references to all of my graphs.

$.each(graphs, function(key, value) {
    $(key).bind("plothover",  function (event, pos, item) {
        $.each(graphs, function(innerKey, innerValue) {
            if(key != innerKey) {
                innerValue.setCrosshair({x: pos.x});
            }
        });
        if(item) {
            var x = item.datapoint[0].toFixed(2),
                y = item.datapoint[1].toFixed(2);
            console.log("x:" + x + ", " + "y:" + y);
        }
    });
});

enter image description here

I'm iterating over the graphs, adding the crosshair and bind it to each other. So, now, when you hover over one of the graphs you'll see the crosshair in the same position on all of the others.

No problems with this. However I'm having problems with the second part of my code:

if(item) {
    var x = item.datapoint[0].toFixed(2),
        y = item.datapoint[1].toFixed(2);
    console.log("x:" + x + ", " + "y:" + y);
}

And the problem is that I'm getting the console.log to print values only when I hover the actual point with my mouse while I want to get that value whenever the crosshair crosses that point, not necessarily the mouse pointer. Any clues what I'm doing wrong or maybe there's a setting in the graph options for that to work?

And another thing is that I can get the value for one graph only - the one my mouse is on, I don't seem to be able to get the values for the rest of the graphs where the crosshair is also moving.

Upvotes: 3

Views: 1152

Answers (1)

Raidri
Raidri

Reputation: 17560

The highlighting with

if(item) {
    var x = item.datapoint[0].toFixed(2),
        y = item.datapoint[1].toFixed(2);
    console.log("x:" + x + ", " + "y:" + y);
}

only works when the cursor is near a point (otherwise item is null).

To get the nearest point to the crosshair, you have to do the highlighting manually by searching the nearest point and interpolate (for every graph). The code for that could look like this:

var axes = value.getAxes();
if (pos.x < axes.xaxis.min || pos.x > axes.xaxis.max ||
    pos.y < axes.yaxis.min || pos.y > axes.yaxis.max) {
    return;
}
$('#output').html("x: " + pos.x.toPrecision(2));

$.each(graphs, function(innerKey, innerValue) {
    var i, series = innerValue.getData()[0];

    // Find the nearest points, x-wise
    for (i = 0; i < series.data.length; ++i) {
        if (series.data[i][0] > pos.x) {
            break;
        }
    }

    // Now Interpolate
    var y,
        p1 = series.data[i - 1],
        p2 = series.data[i];

    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]);
    }

    $('#output').html($('#output').html() + "<br />" + "y (" + innerValue.getData()[0].label + "): " + y.toPrecision(2));

See this fiddle for a full working example. Some Remarks to the new code and fiddle:

  • has sine and cosine values as example data, so uses floating point numbers, change accordingly for int numbers and/or date values
  • uses a <p> element for output instead of the console
  • point-finding and interpolation code can be optimized further if needed (basic version here taken from the example on the Flot page)
  • works only if there is only one data series per graph

Upvotes: 1

Related Questions