Я пытаюсь создать карту координат из некоторых данных, которые я получил в CSV файле. Преобразование осей X/Y отлично работает, круги (или точнее) нарисованы, но подсказка для мыши всегда отображает последние значения (или, вернее, последние значения +1, которые находятся в моем массиве вне пределов, хотя всплывающая подсказка должен быть установлен с текущими значениями массива.
Долгота и высота - это мои два имени массива
var svgContainer = d3.select("body").append("svg")
.attr("width", 700)
.attr("height", 250)
.style("border", "1px solid black");
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
for (i = 0; i < longitude.length; i++) {
var circleSelection = svgContainer.append("circle")
.attr("cx", longitude[i])
.attr("cy", altitude[i])
.attr("r", 2)
.style("fill", "purple")
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div .html("X: " + longitude[i] + " Y: " + altitude[i])
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
}
и здесь css, но я сомневаюсь, что проблему можно найти здесь
<style>
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
Каждый ключ приветствуется
Как правило: не используйте циклы для добавления элементов в коде D3. Мало того, что это не идиоматический D3, но, что более важно, все сломается (как вы видите сейчас).
Прежде всего, здесь объясняется, почему все значения одинаковы: закрытие JavaScript внутри циклов - простой практический пример
Посмотрим на это, наведите указатель на любой круг:
var data = ["foo", "bar", "baz"];
var svg = d3.select("svg");
for (var i = 0; i < data.length; i++) {
svg.append("circle")
.attr("cy", 75)
.attr("cx", 50 + i * 100)
.attr("r", 20)
.attr("fill", "teal")
.on("mouseover", function() {
console.log(data[i - 1])
})
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
Все становится лучше, используя let
:
var data = ["foo", "bar", "baz"];
var svg = d3.select("svg");
for (let i = 0; i < data.length; i++) {
svg.append("circle")
.attr("cy", 75)
.attr("cx", 50 + i * 100)
.attr("r", 20)
.attr("fill", "teal")
.on("mouseover", function() {
console.log(data[i])
})
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
Однако даже если использование let
дает правильный результат, это не очень хорошее решение, потому что вы не привязываете какие-либо данные.
Лучшее решение: используйте выбор "Enter" D3, привязывая данные к элементам:
var data = ["foo", "bar", "baz"];
var svg = d3.select("svg");
svg.selectAll(null)
.data(data)
.enter()
.append("circle")
.attr("cy", 75)
.attr("cx", function(d, i) {
return 50 + i * 100
})
.attr("r", 20)
.attr("fill", "teal")
.on("mouseover", function(d) {
console.log(d)
})
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
.data()
в d3).