最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - D3: finding graph y-coordinate with mouseover - Stack Overflow

programmeradmin7浏览0评论

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: .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!

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!

Share Improve this question edited Jul 7, 2012 at 20:30 Wex 15.7k10 gold badges67 silver badges107 bronze badges asked Jul 6, 2012 at 18:55 registered userregistered user 1011 silver badge3 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 9

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 the code in action: http://jsfiddle/Wexcode/KGxHF/

Here is another example of how you could do this from Mike Bostock: http://bl.ocks/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));
}

I use this code to see value X and Y of each point and draw a circle on my curve on mouse event : exemple on jsFiddle here

Y_value is a global !

var Y_value; 

i define my axes rage

x = d3.time.scale().range([0, w]);
y = d3.scale.linear().range([h, 0]);

i define the circle cursor

var circle = svg.append("circle")
        .attr("r", 8)
        .attr("cx", 0)
        .attr("cy", 0)
        .style({fill: '#fff', 'fill-opacity': .2, stroke: '#000', "stroke-width": '1px'})
        .attr("opacity", 0);

i add a tooltip on my circle

var tooltip = circle.append("svg:title");

and i have my event code

mySensitiveArea.on("mousemove", function() {
    var X_pixel = d3.mouse(this)[0],
        X_date = x.invert(X_pixel);
    var Y_pixel = y(Y_value);

    var pathData = curve1.data()[0]; // recupere donnée de la courbe

    pathData.forEach(function(element, index, array) {
            if ((index+1 < array.length) && (array[index].date <= X_date) && (array[index+1].date >= X_date)) {
                if (X_date-array[index].date < array[index+1].date-X_date)  Y_value = array[index].val;
                else Y_value = array[index+1].val;
            }
        });

        circle.attr("opacity", 1)
            .attr("cx", X_px)
            .attr("cy", Math.round(y(Y_value)));

        tooltip.text("X = " + (X_date) + "\nY = " + (Y_value));
    });
发布评论

评论列表(0)

  1. 暂无评论