Search code examples
d3.jstooltipbar-chartstacked-chart

Can't add title to stacked bar graph on D3


I creating a stacked bar chart using this example. The chart works and renders but I can't add a mouseover label.

I tried this...

  DATE.selectAll("rect")
  .data(function(d) { return d.ages; })
  .enter().append("rect")
  .attr("width", x.rangeBand())
  .attr("y", function(d) { return y(d.y1); })
  .attr("height", function(d) { return y(d.y0) - y(d.y1); })
  .style("fill", function(d) { return color(d.name); });
  .append("svg:title")
  .text(functino(d){return "foo"});

But this after adding the .append("svg:title... the graph stops rendering. If I remove the .style("fill... line, the graph renders, however it's not stacked and there's no mouseover feature.

I have also tried using the tooltip route. (Source)

  .on("mouseover", function() { tooltip.style("display", null); })
  .on("mouseout", function() { tooltip.style("display", "none"); })
  .on("mousemove", function(d) {
    var xPosition = d3.mouse(this)[0] - 15;
  var yPosition = d3.mouse(this)[1] - 25;
  tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")");
tooltip.select("text").text(d.y);
});


// Prep the tooltip bits, initial display is hidden
var tooltip = svg.append("g")
.attr("class", "tooltip")
.style("display", "none");

tooltip.append("rect")
.attr("width", 30)
.attr("height", 20)
.attr("fill", "white")
.style("opacity", 0.5);

tooltip.append("text")
.attr("x", 15)
.attr("dy", "1.2em")
.style("text-anchor", "middle")
.attr("font-size", "12px")
.attr("font-weight", "bold");

But still not luck. Is there a library I need to load? Not sure what's going on.


Solution

  • The graph stop rendering when you try to append the title because you have a typo: it's function, not functino.

    Besides that, this is what you need to get the value of each stacked bar:

    .append("title")
    .text(function(d){
        return d[1]-d[0]
    });
    

    Here is the demo: https://bl.ocks.org/anonymous/raw/886d1749c4e01e191b94df23d97dcaf7/

    But I don't like <title>s. They are not very versatile. Thus, instead of creating another <text>, as the second code you linked does, I prefer creating a div:

    var tooltip = d3.select("body").append("div")
        .attr("class", "tooltip")
        .style("opacity", 0);
    

    Which we position and set the HTML text this way:

    .on("mousemove", function(d) {
        tooltip.html("Value: " + (d[1] - d[0]))
            .style('top', d3.event.pageY - 10 + 'px')
            .style('left', d3.event.pageX + 10 + 'px')
            .style("opacity", 0.9);
    }).on("mouseout", function() {
        tooltip.style("opacity", 0)
    });
    

    And here is the demo: https://bl.ocks.org/anonymous/raw/f6294c4d8513dbbd8152770e0750efd9/