Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple D3 tooltip
<!DOCTYPE html>
<html >
<head>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js"></script>
</head>
<body>
<div class="example_div"></div>
<script type="text/javascript">
var tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("a simple tooltip");
var sampleSVG = d3.select(".example_div")
.append("svg:svg")
.attr("class", "sample")
.attr("width", 300)
.attr("height", 300);
d3.select(".example_div svg")
.append("svg:circle")
.attr("stroke", "black")
.attr("fill", "aliceblue")
.attr("r", 50)
.attr("cx", 52)
.attr("cy", 52)
.on("mouseover", function(){return tooltip.style("visibility", "visible");})
.on("mousemove", function(){return tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");})
.on("mouseout", function(){return tooltip.style("visibility", "hidden");});
</script>
</body>
</html>
@ilyabo

This comment has been minimized.

Copy link

commented Nov 4, 2011

Another way is to use the SVG title element: https://gist.github.com/1339996

@biovisualize

This comment has been minimized.

Copy link
Owner Author

commented Nov 4, 2011

Yes, but the SVG specification leaves it to the user agent to provide the title element as a tooltip ( http://www.w3.org/TR/2000/CR-SVG-20001102/struct.html#DescriptionAndTitleElements ). It is not meant to be. And that's why it's often non-existant, is not stylable, can appear out of the window, etc. But it's simpler to use and be can controlled with plugins. There's a discussion about the title attribute here: https://groups.google.com/d/topic/d3-js/gii2ZTS-BDM/discussion

@ilyabo

This comment has been minimized.

Copy link

commented Nov 4, 2011

I see. Thanks for the link!

@pixeline

This comment has been minimized.

Copy link

commented Jul 21, 2013

Nice!
It would be awesome if the tooltip would reposition itself if the mouse is close to a border. I 'll have a go at it and send you a patch.

@biovisualize

This comment has been minimized.

Copy link
Owner Author

commented Jul 21, 2013

I use this old barebone code example as a template to build more sophisticated one. I can integrate your patch and share a reusable version soon.

@pixeline

This comment has been minimized.

Copy link

commented Jul 21, 2013

Here it is (Note that i'm using jquery here).

    function positionTooltip(mouse, scene, tooltip)
    {
        //Distance of element from the right edge of viewport
        if (scene.width - (mouse.x + tooltip.width) < 20)
        { //If tooltip exceeds the X coordinate of viewport
            mouse.x = mouse.x - tooltip.width - 20;
        }
        //Distance of element from the bottom of viewport
        if (scene.height - (mouse.y + tooltip.height) < 20)
        { //If tooltip exceeds the Y coordinate of viewport
            mouse.y = mouse.y - tooltip.height - 20;
        }
        return {
            top: mouse.y,
            left: mouse.x
        };
    }

usage:

// Early in the code
    var w = $(window).width();
    var h = $(window).height();
    var margin = {
        x: 10,
        y: 10
    };
    var padding = {
        x: 10,
        y: 10
    };
var tooltip = {
        width: $('.tooltip').width(),
        height: $('.tooltip').height(),
    }
    var scene = {
        x: margin.x + padding.x,
        y: margin.y + padding.y,
        width: w - (margin.x * 2) - (padding.x * 2),
        height: h - (margin.y * 2) - (padding.y * 2)
    }

// then, when defining the tooltip div events...

.on("mouseover", function(d)
        {
            div.transition().duration(200).style("opacity", 1);
            //div.html(popupHtml(d)).style("left", (d3.event.pageX + 10) + "px").style("top", (d3.event.pageY - 10) + "px");
            div.html(popupHtml(d)).style("left", function()
            {
                var pos = positionTooltip(
                {
                    x: d3.event.pageX,
                    y: d3.event.pageY
                }, scene, tooltip);
                return (pos.left + 10) + 'px';
            }).style("top", function()
            {
                var pos = positionTooltip(
                {
                    x: d3.event.pageX,
                    y: d3.event.pageY
                }, scene, tooltip);
                return (pos.top - 10) + 'px';
            });
        }).on("mousemove", function(d)
        {
            //div.style("left", (d3.event.pageX + 10) + "px").style("top", (d3.event.pageY - 10) + "px");
            div.style("left", function()
            {
                var pos = positionTooltip(
                {
                    x: d3.event.pageX,
                    y: d3.event.pageY
                }, scene, tooltip);
                return (pos.left + 10) + 'px';
            }).style("top", function()
            {
                var pos = positionTooltip(
                {
                    x: d3.event.pageX,
                    y: d3.event.pageY
                }, scene, tooltip);
                return (pos.top - 10) + 'px';
            });
        }).on("mouseout", function(d)
        {
            div.transition().duration(500).style("opacity", 0);
        });
@Letty

This comment has been minimized.

Copy link

commented Jul 24, 2013

Nice example. But if you try this on firefox your tooltip is under the circle. You should change event.page to d3.event.pageX/Y like in the example from pixeline.

@caged

This comment has been minimized.

Copy link

commented Sep 10, 2013

I've created a simple library for dealing with tooltips in d3 if anyone is interested.

@deanmalmgren

This comment has been minimized.

Copy link

commented Sep 13, 2013

@caged Thanks! this is really helpful +1

@cazzer

This comment has been minimized.

Copy link

commented Dec 3, 2013

If anyone else is getting event is not defined or similar add d3. to the events:

return tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");
@nileshtrivedi

This comment has been minimized.

Copy link

commented Apr 28, 2015

svg:title does work as a tooltip in Firefox 37 and Chrome 42. That's good enough for me! :)

@srinivmw

This comment has been minimized.

Copy link

commented May 13, 2015

Can we apply anything instead of

    .style("left", (d3.event.pageX - 34) + "px")
    .style("top", (d3.event.pageY - 12) + "px"); 

because when i use this the tooltip is not displaying in its position correctly.....

Below two things also not working:
1)

      .style("left", d3.select(this).attr("cx") + "px")     
      .style("top", d3.select(this).attr("cy") + "px");
       .style("left", dx + "px")     
  .style("top", dy + "px");

Can i have good solution for this?

@billwestfall

This comment has been minimized.

Copy link

commented Aug 23, 2016

brilliant and simple, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.