我正在使用D3制作交互式区域图表。当鼠标悬停在区域图表上时,我想在图表的顶部滚动一个点,如下例所示: http://hci.stanford.edu/jheer/files/zoo/ex/time/multiples.html
一旦我获得鼠标位置(使用d3.mouse),我如何将这些坐标转换为相应的数据?使用x标度的倒数(例如x.invert),x轴是直截了当的。但是,我找不到我的图形的相应y坐标。理想情况下,我可以“查找”我的数据中的x坐标并找到相应的y坐标,但不确定如何使用D3执行此操作。谢谢!
答案 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];
}
以下是另一个示例,说明如何从Mike Bostock:http://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));
});