Search code examples
javascriptd3.jstooltip

D3, Adding Tooltip to Horizontal Barchart, tooltip not showing


I'm new to D3 and pretty new to Javascript. My bar chart works as is, but when I add either block of commented out code attempting to add the tool-tip, instead of the tool-tip rendering on top of the bar chart, I get only the bars rendering along with the color fill transition. The x axis, y axis and the text within the bars disappears. What am I doing wrong here?

<script>

            var employees = []
            employees[0] = { name: "Bob", age: 31 }
            employees[1] = { name: "Doug", age: 22 }
            employees[2] = { name: "Christine", age: 58 }
            employees[3] = { name: "Sarah", age: 40 }

            var width = 700;
            var height = 800;

            //create scales
            var widthScale = d3.scale.linear()
                            .domain([0, 58])
                            .range([0, width]);

            var yScale = d3.scale.ordinal()
                        .domain(['200,000', '175,000', '150,000', '125,000', '100,000', '75,000', '50,000', '25,000', '0'])
                        .rangePoints([0, 300]);

            //create axis using scales
            var xAxis = d3.svg.axis()
                      .ticks(10)
                      .tickSize(2)
                      .scale(widthScale);

            var yAxis = d3.svg.axis()
                .orient('left')
                .tickSize(2)
                .scale(yScale)

            //colorscale for bar color transition
            var colorScale = d3.scale.linear()
                            .domain([0, 58])
                            .range(["green", "yellow"]);

            //tooltip------------------------------------------------
            var tooltip = d3.select("body")
                  .append("div")
                  .attr("class", "mytooltip")
                  .style("position", "absolute")
                  .style("background", "white")
                  .style("opacity", "0")
                  .style("display", "none");

            //create canvas
            var canvas = d3.select("body")
                        .append("svg")
                        .attr("width", width)
                        .attr("height", height)
                        .append("g") //create a group
                        .attr("transform", "translate(150, 15)") //right, down

            //create bars & add bars to canvas using data
            var bars = canvas.selectAll("rect")
                        .data(employees)
                        .enter()
                            .append("rect")
                            .attr("y", function (d, i) { return i * 25; })
                            .attr("width", 0)
                            .attr("height", 20)
                        .transition()
                            .delay(function (d, i) { return i * 100; })
                            .duration(600)
                            .attr("width", function (d) { return widthScale(d.age); })
                            .attr("height", 20)
                            .attr("fill", function (d) { return colorScale(d.age); })
                            .attr("y", function (d, i) { return i * 25; })

                            //add tooltip--------------------------------------------------
                            //.on('mouseover', function (d) {

                            //    tooltip.transition()
                            //        .style('opacity', .8)

                            //    tooltip.html(d)
                            //        .style('left', (d3.event.pageX - 35) + 'px')
                            //        .style('top', (d3.event.pageY - 30) + 'px')
                            //  });

            //add text to bars
            canvas.selectAll("text")
                .data(employees)
                .enter()
                    .append("text")
                    .attr("fill", "black")
                    .attr("y", function (d, i) { return i * 25 + 14; })
                    .text(function (d) { return d.name });

            //append a group to canvas, transform & place xAxis on canvas
            canvas.append("g")    
                .attr("transform", "translate(0, 300)")
                .call(xAxis);

            //append a group to canvas, transform & place yAxis on canvas
            canvas.append("g")
                .attr("transform", "translate(0, 0)")
                .call(yAxis);

            //add tooltip-------------------------------------------
            //canvas.append("g")
            //    .on("mouseover", function (d) {
            //        d3.select(this)
            //            .transition()
            //            .duration(500)
            //            .attr("x", function (d) { return x(d.age) - 30; })
            //            .style("cursor", "pointer")
            //  });

        </script>

Solution

  • Apply the mouse listener to the bars and show/hide tooltip div using css opacity.

    var employees = [{
        name: "Bob",
        age: 31
    }, {
        name: "Doug",
        age: 22
    }, {
        name: "Sarah",
        age: 40
    }];
    
    var width = 700;
    var height = 800;
    
    //create scales
    var widthScale = d3.scale.linear()
        .domain([0, 58])
        .range([0, width]);
    
    var yScale = d3.scale.ordinal()
        .domain(['200,000', '175,000', '150,000', '125,000', '100,000', '75,000', '50,000', '25,000', '0'])
        .rangePoints([0, 300]);
    
    //create axis using scales
    var xAxis = d3.svg.axis()
        .ticks(10)
        .tickSize(2)
        .scale(widthScale);
    
    var yAxis = d3.svg.axis()
        .orient('left')
        .tickSize(2)
        .scale(yScale)
    
    //colorscale for bar color transition
    var colorScale = d3.scale.linear()
        .domain([0, 58])
        .range(["green", "yellow"]);
    
    //add tooltip------------------------------------------------
    var tooltip = d3.select("body")
        .append("div")
        .attr("class", "d3-tip")
        .style("position", "absolute")
        .style("opacity", 0);
    
    //create canvas
    var canvas = d3.select("body")
        .append("svg")
        .attr("width", width)
        .attr("height", height)
        .append("g") //create a group
        .attr("transform", "translate(150, 15)") //right, down
    
    
    //create bars & add bars to canvas using data
    var bars = canvas.selectAll(".bar")
        .data(employees)
        .enter()
        .append("g")
        .attr("class","bar");
    
    bars.append("rect")
        .attr("y", function(d, i) {
            return i * 25;
        })
        .attr("width", 0)
        .attr("height", 20)
        .transition()
        .delay(function(d, i) {
            return i * 100;
        })
        .duration(600)
        .attr("width", function(d) {
            return widthScale(d.age);
        })
        .attr("height", 20)
        .attr("fill", function(d) {
            return colorScale(d.age);
        })
        .attr("y", function(d, i) {
            return i * 25;
        });
    
    //add text to bars
    bars.selectAll("text")
        .data(employees)
        .enter()
        .append("text")
        .attr("fill", "black")
        .attr("y", function(d, i) {
            return i * 25 + 14;
        })
        .text(function(d) {
            return d.name
        });
    
    //append a group to canvas, transform & place xAxis on canvas
    canvas.append("g")
        .attr("transform", "translate(0, 300)")
        .call(xAxis);
    
    //append a group to canvas, transform & place yAxis on canvas
    canvas.append("g")
        .attr("transform", "translate(0, 0)")
        .call(yAxis);
    
    //show/hide tooltip-------------------------------------------
    canvas.selectAll(".bar")
        .on("mouseover", function(d) {
            var pos = d3.mouse(this);
            console.log(pos);
            tooltip
                .transition()
                .duration(500)
                .style("opacity", 1)
                .style("left", d3.event.x + "px")
                .style("top", d3.event.y + "px")
                .text(d.name);
        })
        .on("mouseout", function() {
            tooltip.style("opacity", 0);
        });
    .d3-tip {
      line-height: 1;
      font-weight: bold;
      padding: 12px;
      background: rgba(0, 0, 0, 0.8);
      color: #fff;
      border-radius: 2px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>