工具提示始终显示相同的值

时间:2017-10-24 18:58:53

标签: javascript d3.js tooltip

我试图从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;           
}

非常感谢每一条线索

1 个答案:

答案 0 :(得分:1)

作为一般规则:不要使用循环来附加D3代码中的元素。不仅这不是惯用的D3,更重要的是,事情会破裂(正如你现在所看到的那样)。

在此之前,这里解释了为什么所有值都相同:JavaScript closure inside loops – simple practical example

让我们看看这个,将鼠标悬停在任何一个圈子上:

&#13;
&#13;
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])
    })
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
&#13;
&#13;
&#13;

使用let

,情况会好转

&#13;
&#13;
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])
    })
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
&#13;
&#13;
&#13;

但是,即使使用let提供了正确的结果, 也不是一个好的解决方案,因为您没有绑定任何数据。

最佳解决方案是:使用D3&#34;输入&#34;选择,将数据绑定到元素:

&#13;
&#13;
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)
  })
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
&#13;
&#13;
&#13;