Без этого примера я могу неправильно прочитать вашу проблему.
Проблема
Основная проблема возникает из-за итерации текстовых элементов дважды:
area.each(function (d) {
// do something with each element/datum in the selection
})
d3.selectAll("text")
.on("mouseover", function(d) {
// apply an event listner and corrsesponding function to each text element.
})
Проблема в том, что второе вы вкладываете в первое. Для каждого элемента в area
вы выбираете все элементы text
: если у вас есть 2 элемента, вы дважды выделяете весь текст. Вам нужно только один раз выбрать каждый элемент text
.
В имеющемся у вас шаблоне для каждого элемента в area
мы передаем данные этого элемента во вложенную функцию, которая принимает свойство этого элемента данных и с d3.selectAll("text").on("mouseover" ...
применяет эту одиночную к ко всем text
событиям наведения мыши. Поскольку вы делаете это для каждого элемента в area
, мы в конечном итоге перезаписываем прослушиватели событий несколько раз.
Нет, где вы ссылаетесь на текущую датум в цепочке, следующей за d3.selectAll("text")
, поэтому у нас есть только значение из текущей базы данных в текущей итерации .each()
.
Решение
Вам не нужно использовать .each()
здесь, чтобы применить прослушиватель событий, .on()
должно быть достаточно.
У нас есть наши функции наведения и наведения указателя мыши:
function mouseover(d) {
tooltip
.style("opacity", 0.9)
.text(d.x)
.style('left', `${d3.event.pageX + 10}px`)
.style('top', `${d3.event.pageY - 18}px`);
}
function mouseout() {
tooltip
.style("opacity",0);
}
Затем мы можем вызвать его с помощью:
selection.on("mouseover",mouseover)
.on("mouseout",mouseout);
И мы можем повторно использовать это для множественного выбора или элементов. Указанные датум c для каждого элемента будут использоваться для определения текста всплывающей подсказки.
var tooltip = d3.select(".tooltip");
var svg = d3.select("svg");
var data = [{x: 10},{x:50},{x:90},{x:130},{x:170},{x:210},{x:250},{x:290},{x:330}]
var g = svg.selectAll(null)
.data(data)
.enter()
.append("g")
.attr("transform",function(d) { return "translate("+[d.x,0]+")"; })
var rect = g.append("rect")
.attr("width", 35)
.attr("height", 100)
.attr("fill","steelblue")
.on("mousemove",mouseover)
.on("mouseout",mouseout)
var text = g.append("text")
.attr("y", 120)
.attr("x", 18)
.style("text-anchor","middle")
.text(function(d) { return d.x; })
.on("mouseover",mouseover)
.on("mouseout",mouseout)
function mouseover(d) {
tooltip
.style("opacity", 0.9)
.text(d.x)
.style('left', `${d3.event.pageX + 10}px`)
.style('top', `${d3.event.pageY - 18}px`);
}
function mouseout() {
tooltip
.style("opacity",0);
}
.tooltip {
position: absolute;
padding: 5px;
background: yellow;
}
rect, text {
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div class="tooltip"></div>
<svg width="400" height="300"></svg>