Search code examples
javascriptd3.jschartstooltip

D3tip and stacked bar charts


I've previously made a really neat bar chart using d3 and d3tip with some help from StackOverflow (result here). This time I'm trying to achieve something similar with d3tip whilst using a stacked bar chart. I've managed to create the stacked bar chart using examples found on the web, but I can't manage to get the tip to work (snippet of stacked bar chart here).

As you can see in the snippet I've tried to achieve this using the following code:

    svg.selectAll(".g")
    .data(data)
    .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) {
        return x(d.Year);
    })
    .attr("width", x.rangeBand())
    .attr("y", function(d) {
        return y(d.N);
    })
    .attr("height", function(d) {
        return height - y(d.N);
    })
    .on('mouseover', tip.show)
    .on('mouseout', tip.hide);

Which worked perfectly fine previously. Yet for some reason when I mouseover the bars, nothing is shown. I expected to encounter some problems with the stacked portions, but I don't understand why no tip is shown at all.

The content of the tip is still to be developed (I'm still debating what exactly I want to display) but I believe it should be showing a tip at least. What am I missing here?


Solution

  • Your mouseover is in the wrong place. Before you had a bar chart and now you have a stacked bar chart (obviously), but the data brought back will be different.

    For example, your mouseover doesnt do anything, because the place where it's called doesn't do anything.

    So I have changed the mouse over to where you need it and the data logged is as follows :

    Object {name: "Trek", y0: 43, y1: 86}
    

    So instead of d.Year & d.N, the only data you can bring back is d.name. This is due to the data being brought through making the stacks :

      data.forEach(function(d) {
        var y0 = 0;
        d.ages = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
        d.total = d.ages[d.ages.length - 1].y1;
      });
    

    So I have updated you tip to this :

    return "<strong>Name:</strong> <span style='color: #DA6A26'>" + d.name + "</span>" 
    

    And moved your mouseover to line 100 :

    .on('mouseover', function(d){
              console.log('mouseover');
              console.log(d)
             tip.show(d);
            } )
            .on('mouseout', tip.hide);
    

    I have left the logs in there for you so you can see what data is outputted.

    Updated plnkr : http://plnkr.co/edit/nrslJjlM37Hu5DR2ZBXw?p=preview

    By the way your link to the css file was wrong. So instead of css/style.css it should just be style.css

    Now on mouseover, you get name. If you don't want this then you need to bring the correct data through when creating the stacks. I.e on this line :

     d.ages = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });