D3 Bar Chart - tooltip not positioning properly

Hi, I’m having trouble with the Visualise data with a bar chart challenge. I can’t get the tooltip to display next to the bar I hover over.

I created a rectangle object to start with, and was hoping the position would update with the code I added, but it doesn’t seem to work.

Here’s the codepen: https://codepen.io/jesswebber/pen/qBrEGNr

Any help would be much appreciated.
Thank you

Your div in

.on("mouseover", function(d) {
       div.transition()
         .duration(200)
         .style("opacity", .9);
      div.html("text goes here")
         .style("left", (d3.event.pageX) + "10px")
         .style("top", (d3.event.pageY - 28) + "10px");
      })

is undefined. You need to have something like this

const tooltip = d3.select('#barchart')
      .append('div')
      .attr('id', 'tooltip')
      .style('opacity', 0)

You can specify other attributes right in the code or specify them in css. And then you specify tooltip attr and style in ‘mouseenter’

.on('mouseenter', function (e, d) {
        /* specify tooltip here */
       /* don't forget to assign 'data-date' attr  */
})

Notice that with v6 D3 we get event e and data d in the callback function. You can use e.pageX and e.pageY for the mouse click point.

(e.pageX + 10 ) + 'px' //shift 10 pixels to right

One last point. Your code

(d3.event.pageX) + "10px"

will end up in a wrong value like “24010px”! It should be

(d3.event.pageX) + 10 + "px"
1 Like

Thanks very much for your help @twotani . The const tooltip… section helped a lot. I still couldn’t get the mouseenter function to work but eventually settled on this code that worked for me:

      .on("mouseover", function(event, d) {
      const[x, y] = d3.pointer(event);
      tooltip.attr("visibility", "visible")  
      tooltip.style("opacity", .9);
      tooltip.attr("data-date", d[0])
      const val = d3.format(",.1f")(d[1]);
      tooltip.html("$" + val + " billion" + " " + d[0])
        .style("left", (x) + "px")
        .style("top", (y) + "px");
    })
      .on("mouseout", function(event, d) {
      const[x, y] = d3.pointer(event)
      tooltip.transition()
         .duration(200)
         .delay(100)
      tooltip.style("opacity", 0);
  });
1 Like

Glad to hear your code is working. I was also handling mouseover, but I switched to handling mouseenter. Handling mouseenter seems to result in a more stable behavior of the tooltip. When I was handling mouseover, I noticed that moving mouse very quickly sometimes resulted in the tooltip remaining on the screen. I think using either event is fine (as long as we pass the FCC tests :smile:).

I forgot to mention that you probably want to set

pointer-events: none; /* critical to disable mouse */

for the tooltip attribute. This is my styling for #tooltip in my CSS file

#tooltip {
  position: absolute;
  max-width: 200px;
  height: auto;
  padding: 5px;
  color: white;
  background-color: rgb(6, 44, 56);
  border-radius: 5px;
  box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.5);
  pointer-events: none; /* CRITICAL disable mouse */
  font-family: Arial, Helvetica, sans-serif;
  font-size: medium;
}

Several different sources indicated to do this. You might try it and see what happens.

Lastly, a minor point. Since you’re setting opacity, I don’t think you need to set visibility.

Thanks. Yes, added the “pointer-events: none” line in.
I just have test 10 left to pass now. Did you manage to pass this?

You applied yScale when assigning the y position, but you didn’t use xScale for the x position. Your xScale is based on scaleTime, so the x position of the rect needs to match that. This is how I’m assigning the x position

.attr("x", (d, i) => xScale(dates[i]))

My xScale and dates are computed as

dates = dataset.map((d) => new Date(d[0])); 

xScale = d3.scaleTime()
                    .domain( [d3.min(dates), d3.max(dates)])
                    .range([0, svgWidth]);

You need to play around a bit to fit your situation. If you adjust the width and height of svg by adding some padding, that could impact how you assign the x and y values. You will encounter this issue in latter projects too. I played around and made them work, but I now know the importance of defining and applying xScale and yScale properly so everything fits together correctly.

Thanks! Will see if that works

Finally passed it so thanks again @twotani for your help!

Cheers.

I got the “axis and data do not match” errors in all projects. :face_with_raised_eyebrow: :unamused: So watch out for that and have fun with other D3 projects.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.