Подсказка всегда отображает одно и то же значение

1

Я пытаюсь создать карту координат из некоторых данных, которые я получил в 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;           
}

Каждый ключ приветствуется

  • 0
    У вас есть js fiddle или какая-то демо-зона, которую вы можете настроить? Сначала я подумал, что вы не привязываете данные к элементам DOM, как это должно происходить в d3 (посмотрите на метод .data() в d3).
  • 0
    о спасибо большое, похоже это моя проблема
Теги:
d3.js
tooltip

1 ответ

1

Как правило: не используйте циклы для добавления элементов в коде 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>

Ещё вопросы

Сообщество Overcoder
Наверх
Меню