D3: finding graph y-coordinate with mouseover

http://stackoverflow.com/questions/11368096/d3-finding-graph-y-coordinate-with-mouseover

by Wexcode

HTML

<script src="http://d3js.org/d3.v2.min.js"></script>

CSS

path { stroke: #000; fill: brown; stroke-width: .5px }
circle { fill: red; }

JavaScript

var SPACING = 5;

var data = d3.range(50).map(function(d, i) {
    return {x: i * SPACING, y: (Math.random()*100)};
});
var h = d3.max(data, function(d) { return d.y; }) + 15;

/* Create the lookup table */
var table = [];
data.forEach(function(d) {
    table[d.x] = d.y;
});

var svg = d3.select("body").append("svg")
    .attr("width", 410)
    .attr("height", 125)
.append("g")
    .attr("transform", "translate(5, 5)");
    
var area = svg.selectAll("path").data([data]).enter().append("path")
    .attr(
        "d",
        d3.svg.area()
            .x(function(d) { return d.x; })
            .y0(h)        
            .y1(function(d) { return d.y; })
    );

var circle = svg.append("circle")
    .attr("r", 3)
    .attr("display", "none");

area
    .on("mouseover", function() { circle.attr("display", "block"); })
    .on("mousemove", update)
    .on("mouseout", function() { circle.attr("display", "none"); });

function update() {    
    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];
    }
    
    circle
        .attr("cx", x)
        .attr("cy", y);
}