Flot Stacked Bar Chart and displaying bar values on mouse over
Asked Answered
H

4

22

I'm trying to understand the tooltip functionality of Flot but not really getting my head around it!

I am trying to achieve a tooltip that displays the label and value of each section of a stacked bar chart

Would someone be able to point my towards an example of this or provide code for doing so?

Haase answered 13/8, 2010 at 11:29 Comment(0)
Y
24

The following code works for my Flot stacked bar chart, based on the Flot example that shows data point hover. The trick is that the 'item' values in the stacked chart are cumulative, so the 'y' value displayed in the tool tip has to first subtract the datapoint for the bars underneath.

var previousPoint = null;
$("#chart").bind("plothover", function (event, pos, item) {
    if (item) {
        if (previousPoint != item.datapoint) {
            previousPoint = item.datapoint;

            $("#tooltip").remove();
            var x = item.datapoint[0],
                y = item.datapoint[1] - item.datapoint[2];

            showTooltip(item.pageX, item.pageY, y + " " + item.series.label);
        }
    }
    else {
        $("#tooltip").remove();
        previousPoint = null;            
    }
});

I did not find this in the Flot documentation, but the item.datapoint array seemed to contain what I needed in practice.

Yearround answered 13/8, 2010 at 12:54 Comment(3)
showTooltip() is implemented here (View Source): flotcharts.org/flot/examples/interacting/index.htmlMandorla
@peter What if I want to show percentage area covered by each stack instead of its value.Wertheimer
A more general solution (which works for more than two series) is to subtract all subsequent data points, i.e. y = item.datapoint[1]; for ( var i = 2; i < item.datapoint.length; ++i ) y -= item.datapoint[i];.Ligule
A
2

The code above caused redraw-issues for me. Here is an improved code:

var previousPoint = [0,0,0];
$("#regionsChart").bind("plothover", function (event, pos, item) {
    if (item) {
        if (previousPoint[0] != item.datapoint[0]
            || previousPoint[1] != item.datapoint[1]
            || previousPoint[2] != item.datapoint[2]
        ) {
            previousPoint = item.datapoint;

            $("#tooltip").remove();
            var x = item.datapoint[0],
                y = item.datapoint[1] - item.datapoint[2];

            showTooltip(item.pageX, item.pageY, item.series.label + " " + y.toFixed(0) );
        }
    }
    else {
        $("#tooltip").remove();
        previousPoint = [0,0,0];
    }
});
Albumenize answered 10/9, 2013 at 17:17 Comment(0)
C
0

This is the same as Thomas above, except that I shifted the tooltip up to prevent it blocking the hover action.

var previousPoint = [0,0,0];
$("#regionsChart").bind("plothover", function (event, pos, item) {
    if (item) {
        if (previousPoint[0] != item.datapoint[0]
            || previousPoint[1] != item.datapoint[1]
            || previousPoint[2] != item.datapoint[2]
        ) {
            previousPoint = item.datapoint;

            $("#tooltip").remove();
            var x = item.datapoint[0],
                y = item.datapoint[1] - item.datapoint[2];

            showTooltip(item.pageX, item.pageY - 35, item.series.label + " " + y.toFixed(0) );
        }
    }
    else {
        $("#tooltip").remove();
        previousPoint = [0,0,0];
    }
});
Culet answered 2/2, 2015 at 10:6 Comment(0)
I
0

The solution is using tooltipOpts -> content method with a callback function to properly return dynamic data to the label.

I figured out that passing a 4th argument to the callback function of the "tooltipOpts" actually gives you the whole data object from which the chart/graph is constructed from. From here, you can easily extract the X axis labels, using the second argument of this same function as the index of the label to extract.

EXAMPLE:

Data object I'm passing to the plot function:

[
    { data: [[1,137],[2,194],[3,376],[4,145],[5,145],[6,145],[7,146]] }
],
{
    bars: { show: true, fill: true, barWidth: 0.3, lineWidth: 1, fillColor: { colors: [{ opacity: 0.8 }, { opacity: 1}] }, align: 'center' },
    colors: ['#fcc100'],
    series: { shadowSize: 3 },
    xaxis: {
        show: true,
        font: { color: '#ccc' },
        position: 'bottom',
        ticks: [[1,'Thursday'],[2,'Friday'],[3,'Saturday'],[4,'Sunday'],[5,'Monday'],[6,'Tuesday'],[7,'Wednesday']]
    },
    yaxis:{ show: true, font: { color: '#ccc' }},
    grid: { hoverable: true, clickable: true, borderWidth: 0, color: 'rgba(120,120,120,0.5)' },
    tooltip: true,
    tooltipOpts: {
        content: function(data, x, y, dataObject) {
            var XdataIndex = dataObject.dataIndex;
            var XdataLabel = dataObject.series.xaxis.ticks[XdataIndex].label;
            return y + ' stories created about your page on ' + XdataLabel
        },
        defaultTheme: false,
        shifts: { x: 0, y: -40 }
    }
}

Bar chart rendered from the above data object:

enter image description here

As you can see on the image preview, the logic used to render the label's content dynamically form the actual data is this:

tooltipOpts: {
    content: function(data, x, y, dataObject) {
        var XdataIndex = dataObject.dataIndex;
        var XdataLabel = dataObject.series.xaxis.ticks[XdataIndex].label;
        return y + ' stories created about your page on ' + XdataLabel;
    },
    defaultTheme: false,
    shifts: { x: 0, y: -40 }
}
Ionosphere answered 23/11, 2017 at 12:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.