I am making an interactive area chart using D3. While mousing over the area-chart, I'd like to have a dot rolling along the top of the chart, as in the following example: http://hci.stanford.edu/jheer/files/zoo/ex/time/multiples.html
Once I get the mouse position (using d3.mouse), how do I translate these coordinates to the corresponding data? The x-axis is straightforward using the inverse of the x-scale (e.g. x.invert). However, I can't find the corresponding y-coordinate for my graph. Ideally I could "look up" the x-coordinate in my data and find the corresponding y-coordinate, but not sure how to do this with D3. Thanks!
It's actually relatively easy to create your own lookup table:
/* Create the lookup table */
var table = {};
data.forEach(function(d) {
table[d.x] = d.y;
});
This is a viable solution if you have enough data points, but it's likely that you will probably need to use some sort of rounding or interpolator to fill in the intermediate x-values. For instance, if there is a fixed spacing between your points, you can use a linear interpolator and do the following calculations to get the coordinates for your circle on mouseover
:
var x = d3.mouse(this)[0];
var y;
if ( table[x] === undefined ) {
var lower = x - (x % SPACING);
var upper = lower + SPACING;
var between = d3.interpolateNumber(table[lower], table[upper]);
y = between( (x % SPACING) / SPACING );
} else {
y = table[x];
}
Here is another example of how you could do this from Mike Bostock: http://bl.ocks.org/3025699
mbostock (D3.js author) implement this here
svg.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.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.attr("transform", "translate(" + x(d.date) + "," + y(d.close) + ")");
focus.select("text").text(formatCurrency(d.close));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With