Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3 stacked bar mouse over whole bar

I have created a stacked bar graph using a tutorial. The stack is created with the following:

var layers = d3.layout.stack()(["passed", "failed", "skipped"].map(function(cause){
        return data.map(function(d){
            return {x: d.UP, y: +d[cause]};
            });
        }));

When I hover my mouse over a stack, I want the whole stack to be marked (e.g. stronger border line).

I am currently using:

var barMouseOverFunction = function(d, i) {
    var bar = d3.select(this);
    bar.attr("stroke", "black" );

However this only changes for the current stack. Any ideas of how to get all the bars in the stack?

EDIT FULLCODE:

d3.json('db/data.php', function(data) {             


    var layers = d3.layout.stack()(["passed", "failed", "skipped"].map(function(cause){
        return data.map(function(d){
            return {x: d.UP, y: +d[cause]};
            });
        }));



    var n = 3, // number of layers
        stack = d3.layout.stack(),
        yGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y; }); }),
        yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });




    var x = d3.scale.ordinal()
        .domain(data.map(function(d){return d.UP;}))
        .rangeRoundBands([0, width], .4);


    var y = d3.scale.linear()
        .domain([0, yStackMax])
        .range([height, 0]);

    var color = d3.scale.ordinal()
        .range(["#6ad46a", "#ed2828", "#fae650"]);

    var xAxis = d3.svg.axis()
        .scale(x)
        .tickSize(0)
        .tickPadding(6)
        .orient("bottom");

        // Grid lines
    var gridcontainer = svg.append('g');
    gridcontainer.selectAll("line").data(y.ticks(10)).enter().append("line")
        .attr("x1", 0)
        .attr("x2", width)
        .attr("y1", y)
        .attr("y2", y)
        .style("stroke", "#87cbff")
        .style("stroke-width", .3);

    var layer = svg.selectAll(".layer")
        .data(layers)
      .enter().append("g")
        .attr("class", "layer")
        .style("fill", function(d, i) { return color(i); })
        .style("stroke", function(d, i){return d3.rgb(color(i)).darker();});

    var timeformatter = d3.time.format("%b %e %Y %x%p");

    // On mouseover display test case information
    var barMouseOverFunction = function(d, i) {
        var bar = d3.select(this);
        bar.attr("stroke", "black" );

        var dataItem = data[i];
    }


    var barMouseOutFunction = function() {
        var bar = d3.select(this);
        bar.attr("stroke", function(d){
            return StatusColor(d.result);
        });

        d3.select("p").text("");
    }





    var rect = layer.selectAll("rect")
        .data(function(d) { return d; })
      .enter().append("rect")
        .attr("x", function(d) { return x(d.x); })
        .attr("y", height)
        .attr("width", x.rangeBand())
        .attr("height", 0)
        .attr("rx", 0.5)
        .attr("ry", 0.5)
        .on("mouseover", barMouseOverFunction)
        .on("mouseout", barMouseOutFunction);
like image 454
peter Avatar asked Nov 19 '25 17:11

peter


1 Answers

The easiest way to do this is probably to assign a separate class to the bars for a particular stack and then select based on that, i.e. something like

var rect = layer.selectAll("rect")
    .data(function(d) { return d; })
    .enter().append("rect")
    .attr("class", function(d, i, j) { return "stack" + j; })
...

var barMouseOverFunction = function(d, i, j) {
    d3.selectAll("rect.stack" + j).attr("stroke", "black");
    var dataItem = data[i];
}
like image 168
Lars Kotthoff Avatar answered Nov 21 '25 07:11

Lars Kotthoff



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!