D3:使用鼠标悬停找到图形y坐标

时间:2012-07-06 18:55:44

标签: javascript html css svg d3.js

我正在使用D3制作交互式区域图表。当鼠标悬停在区域图表上时,我想在图表的顶部滚动一个点,如下例所示: http://hci.stanford.edu/jheer/files/zoo/ex/time/multiples.html

一旦我获得鼠标位置(使用d3.mouse),我如何将这些坐标转换为相应的数据?使用x标度的倒数(例如x.invert),x轴是直截了当的。但是,我找不到我的图形的相应y坐标。理想情况下,我可以“查找”我的数据中的x坐标并找到相应的y坐标,但不确定如何使用D3执行此操作。谢谢!

3 个答案:

答案 0 :(得分:9)

创建自己的查找表实际上相对容易:

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

如果您有足够的数据点,这是一个可行的解决方案,但您可能需要使用某种舍入或插值来填充中间x值。例如,如果点之间有固定的间距,则可以使用线性插值器并执行以下计算以获取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];
}

以下是操作中的代码:http://jsfiddle.net/Wexcode/KGxHF/

以下是另一个示例,说明如何从Mike Bostockhttp://bl.ocks.org/3025699

执行此操作

答案 1 :(得分:2)

mbostock(D3.js作者)实现此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));
}

答案 2 :(得分:1)

我使用此代码查看每个点的值X和Y,并在鼠标事件的曲线上画一个圆圈: 例如jsFiddle here

Y_value是全球性的!

var Y_value; 

我定义了我的轴愤怒

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

我定义圆圈光标

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);

我在我的圈子上添加工具提示

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

我有我的事件代码

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));
    });