Instantly share code, notes, and snippets.

@d3noob /atad.csv
Last active May 30, 2018

Embed
What would you like to do?
Favorite tooltip (complex version)

This is a follow on from the favorite simple tooltip graph used as an example in the book D3 Tips and Tricks.

It impliments a more complex example than the simple version and is designed to illustrate additional things you can do with the technique. It should be taken in context with the text of the book which can be downloaded for free from Leanpub.

date close
26-Mar-12 606.98
27-Mar-12 614.48
28-Mar-12 617.62
29-Mar-12 609.86
30-Mar-12 599.55
2-Apr-12 618.63
3-Apr-12 629.32
4-Apr-12 624.31
5-Apr-12 633.68
9-Apr-12 636.23
10-Apr-12 628.44
11-Apr-12 626.20
12-Apr-12 622.77
13-Apr-12 605.23
16-Apr-12 580.13
17-Apr-12 543.70
18-Apr-12 443.34
19-Apr-12 345.44
20-Apr-12 234.98
23-Apr-12 166.70
24-Apr-12 130.28
25-Apr-12 99.00
26-Apr-12 89.70
27-Apr-12 67.00
30-Apr-12 53.98
1-May-12 58.13
<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */
body { font: 12px Arial;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
</style>
<body>
<!-- load the d3.js library -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%d-%b-%y").parse,
formatDate = d3.time.format("%d-%b"),
bisectDate = d3.bisector(function(d) { return d.date; }).left;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
// Adds the svg canvas
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
var lineSvg = svg.append("g");
var focus = svg.append("g")
.style("display", "none");
// Get the data
d3.csv("atad.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.close; })]);
// Add the valueline path.
lineSvg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// append the x line
focus.append("line")
.attr("class", "x")
.style("stroke", "blue")
.style("stroke-dasharray", "3,3")
.style("opacity", 0.5)
.attr("y1", 0)
.attr("y2", height);
// append the y line
focus.append("line")
.attr("class", "y")
.style("stroke", "blue")
.style("stroke-dasharray", "3,3")
.style("opacity", 0.5)
.attr("x1", width)
.attr("x2", width);
// append the circle at the intersection
focus.append("circle")
.attr("class", "y")
.style("fill", "none")
.style("stroke", "blue")
.attr("r", 4);
// place the value at the intersection
focus.append("text")
.attr("class", "y1")
.style("stroke", "white")
.style("stroke-width", "3.5px")
.style("opacity", 0.8)
.attr("dx", 8)
.attr("dy", "-.3em");
focus.append("text")
.attr("class", "y2")
.attr("dx", 8)
.attr("dy", "-.3em");
// place the date at the intersection
focus.append("text")
.attr("class", "y3")
.style("stroke", "white")
.style("stroke-width", "3.5px")
.style("opacity", 0.8)
.attr("dx", 8)
.attr("dy", "1em");
focus.append("text")
.attr("class", "y4")
.attr("dx", 8)
.attr("dy", "1em");
// append the rectangle to capture mouse
svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all")
.on("mouseover", function() { focus.style("display", null); })
.on("mouseout", function() { focus.style("display", "none"); })
.on("mousemove", mousemove);
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1),
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
focus.select("circle.y")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")");
focus.select("text.y1")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.text(d.close);
focus.select("text.y2")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.text(d.close);
focus.select("text.y3")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.text(formatDate(d.date));
focus.select("text.y4")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.text(formatDate(d.date));
focus.select(".x")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.close) + ")")
.attr("y2", height - y(d.close));
focus.select(".y")
.attr("transform",
"translate(" + width * -1 + "," +
y(d.close) + ")")
.attr("x2", width + width);
}
});
</script>
</body>
@arnavbose

This comment has been minimized.

Copy link

arnavbose commented Jun 29, 2015

Hi,

I want to use the complex version of the tooltip in my chart. It is working properly for single line chart. But the moment I try to use it for multi line chart, it's not working. I have three lines in my chart but the dotted points come only for one of the charts. Could you tell me how this code can work for multi line charts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment