Please see the working example below. You can hover over the
rectangles to see the tooltip (I have deliberately left the opacity
greater than zero for them for the purpose of this example). As you
can see the tooltip appears above the mouse pointer. I want the
tooltip to appear above the mouse pointer when the pointer is above
the drawn path and below the mouse pointer when mouse pointer is below
the path. One way I can think of doing this is to find the mouse
location in the svg figure, its (xcoord, ycoord) and then comparing
this ycoord with the path's y value when x = xcoord.
I tried adding the line console.log(d3.svg.mouse(this)) and also
console.log(d3.mouse(this)) to the addtooltip() function to see if I
could get the mouse location relative to the origin of the SVG figure.
However, doing so gives me the following error when I hover my mouse
on any of the rectangles:
Uncaught TypeError: Object [object DOMWindow] has no method
'getBoundingClientRect'
Any ideas how I can achieve what I want.
Thanks for reading this.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript"
src="http://mbostock.github.com/d3/d3.js"></script>
<style type="text/css">
div.tooltip {
position: absolute;
text-align: center;
z-index: 50;
width: 140px;
height: auto;
padding: 8px;
font: 24px sans-serif;
background: red;
color: white;
border: solid 1px #aaa;
border-radius: 8px;
opacity: 0.8;
}
</style>
</head>
<body>
<div id="viz"></div>
<script type="text/javascript">
var w = 600;
var h = 500;
canvas = d3.select("#viz")
.append("svg:svg")
.attr("width", w)
.attr("height", h);
group1 = canvas.append("svg:g");
var xunscaled = d3.range(10, 40);
console.log(xunscaled);
var genydata = function(x){
return 20 + 2*(Math.pow(x,1.3));
}
yunscaled = xunscaled.map(genydata);
console.log(yunscaled);
xscale = d3.scale.linear().domain([0,40]).range([0,w]);
yscale = d3.scale.linear().domain([20,275]).range([0,h]);
plotData = d3.zip(xunscaled,yunscaled);
console.log(plotData);
d3line = d3.svg.line()
.x(function(d){return xscale(d[0]);})
.y(function(d){return h - yscale(d[1]);})
.interpolate("linear");
group1.append("svg:path")
.attr("d", d3line(plotData))
.style("stroke-width", 2.5)
.style("stroke", "steelblue")
.style("fill", "none");
//****************************************************
// Create rectangles for tooltips
//****************************************************
var rectH = 80;
var rectW = 10;
group1.selectAll("rect.tooltip")
.data(plotData)
.enter()
.append("svg:rect")
.attr("x", function(d){return xscale(d[0]) - (rectW/2);})
.attr("y", function(d){return h - yscale(d[1]) - (rectH/2);})
.attr("width", rectW)
.attr("height", rectH)
.style("z-index", 10)
.style("stroke-width", 1)
.style("stroke", "steelblue")
.style("stroke-opacity", 0.5)
.style("fill", "orange")
.style("fill-opacity", 0.4)
.on("mouseover", function(d){return addtooltip(d);})
.on("mouseout", function(d){return removetooltip();});
//**************************************
// Tooltip
//**************************************
var addtooltip = function(d){
// Round the ratio to two decimal places
adrdRatio = Math.round(Math.pow(10,2) * d[1])/Math.pow(10,2);
// console.log(d3.mouse(this)); //This line gives error
when uncommented.
// Tooltip box with information
d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("top", (d3.event.pageY-90) + "px")
.style("left",(d3.event.pageX-90) + "px")
.html("<table><tr><td>X: </td><td align=left>" + d[0] +
"</td></tr> <tr><td>Y: </td><td align=left>" + adrdRatio +
"</td></tr></table>");
}
var removetooltip = function(){
d3.select("div.tooltip")
.remove();
d3.select("#highlight").remove();
}
</script>
</body>
</html>
.on("mouseover", function(d){return addtooltip(d);})
.on("mouseout", function(d){return removetooltip();});
To this:
.on("mouseover", addtooltip)
.on("mouseout", removetooltip);
Mike
And why was that? Presumably your browser gave you an error which
might help you debug the problem. I'll give you a hint. What is the
difference between these two bits of code?
#1
var addtooltip = function(d) {
// show tooltip here
};
#2
function addtooltip(d) {
// show tooltip here
}
Mike
Thanks for your response. I did look for error in the Chrome console,
but it did not show any error.
Anyhow, I changed the function definition from #1 to #2, and it now
works. Next, I need to go and understand properly the difference
between these two ways of defining the function. I don't know much
javascript and I appreciate you pointing me in the right direction.
There's a detailed explanation here:
http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
Mike