Birish
Birish

Reputation: 5832

Adding tooltip to donut slices

I'm trying to add a tooltip to my donut's slices on moues over as follow:

var tooltip = select("g.arc--first")
    //.append("div") // if I add this div here it stops working
    .append("text")

firstSlice.append('path')
    .attr('d', coolArc(firstRadius, thickness))
    .attr('class', d => `fill_${weightScale(d.data.weight)}`)
    .on('mouseover', (d) => {
       tooltip.style("visibility", "visible")
              .text(this.nodeByName.get(d.data.name)["Short Description"])
              .style("fill", "red")
              .style("position", "absolute")
              .style("text-align", "center")
              .style("width", "60px")
              .style("height", "28px")
              .style("padding", "2px")
              .style("background", "lightsteelblue")
              .style("border", "10px")
    })

My goal is to have a tooltip similar to http://bl.ocks.org/d3noob/a22c42db65eb00d4e369 , but right now it only shows a red text at the middle of the page. I think I need to have a new div but when I try to add append("div") it stops working and doesn't show the text anymore. How should I fix it?

Upvotes: 1

Views: 646

Answers (1)

Mikhail Shabrikov
Mikhail Shabrikov

Reputation: 8509

The tooltip from the example that you mentioned works pretty simply. It is appended as a child element for body (you try to append it as a child for g element, but you cannot append html elements into svg). So you should change you code:

var tooltip = select('body')
    .append('div')
    .attr('class', 'tooltip');

I also recommend you style this tooltip in your css (add appropriate class name and rules in your css file) you can avoid chaining many .style methods in this case. You should set position: absolute; rule - you can update top and left styles and position the tooltip where you need. Also set visibility: hidden rule - your tooltip should be hidden by default.

In mouseover event handler you need to change:

visibility style to show the tooltip

left and top styles to position the tooltip

text to update text on the tooltip

.on('mouseover', (d) => {
  tooltip
    .style('visibility', 'visible')
    .style('left', d3.event.pageX + 'px')
    .style('top', d3.event.pageY + 'px')
    .text(d);
})

In mouseout event handler you should just hide the tooltip:

.on('mouseout', (d) => {
  tooltip
    .style('visibility', 'hidden')
});

See simplified demo in the hidden snippet below:

var tooltip = d3.select("body")
    .append("div")
    .attr('class', 'tooltip');
    
d3.selectAll('circle')
	.data(['one', 'two', 'three'])
	.on('mouseover', (d) => {
  	tooltip
    	.style('visibility', 'visible')
    	.style('left', d3.event.pageX + 'px')
    	.style('top', d3.event.pageY + 'px')
      .text(d);
	})
  .on('mouseout', (d) => {
  	tooltip
    	.style('visibility', 'hidden')
	})
.tooltip {
  background-color: lightblue;
  font-weight: bold;
  padding: 5px;
  border-radius: 9px;
  position: absolute;
  display: inline-block;
  margin-top: -50px;
  visibility: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.js"></script>
<svg width="720" height="120">
  <circle cx="20" cy="60" r="10"></circle>
  <circle cx="180" cy="60" r="10"></circle>
  <circle cx="340" cy="60" r="10"></circle>
</svg>

Upvotes: 2

Related Questions