D3: поиск графа y-координаты с помощью мыши
Я делаю интерактивную диаграмму области, используя D3. В то время как мышь над диаграммой области, я хотел бы, чтобы точка прокатилась по верхней части диаграммы, как в следующем примере:
http://hci.stanford.edu/jheer/files/zoo/ex/time/multiples.html
Как только я получу позицию мыши (используя d3.mouse), как мне перевести эти координаты в соответствующие данные? Ось X проста, используя инверсию x-scale (например, x.invert). Однако я не могу найти соответствующую координату y для моего графика. В идеале я мог бы "найти" координату x в своих данных и найти соответствующую координату y, но не знаю, как это сделать с D3. Спасибо!
Ответы
Ответ 1
На самом деле относительно легко создать собственную таблицу поиска:
/* 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://bl.ocks.org/3025699
Ответ 2
mbostock (автор D3.js) реализует это здесь
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));
}
Ответ 3
Я использую этот код, чтобы увидеть значение X и Y каждой точки и нарисовать круг на моей кривой на событии мыши:
пример jsFiddle здесь
Y_value является глобальным!
var Y_value;
я определяю свою ось осязания
x = d3.time.scale().range([0, w]);
y = d3.scale.linear().range([h, 0]);
i определите курсор круга
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));
});