d3.js中数组元素的绑定

时间:2014-09-17 20:24:26

标签: javascript d3.js

Basiclly我有一些字符串数组,我想将每个字符串绑定到一个圆圈。然后,当我将鼠标悬停在圆圈上时,我想在工具提示中显示这些字符串。

所以这是我的数组:

var node = [
        "Hallo Hallo Hallo Hallo Hallo Hallo Hallo",
        "foobarbaz",
        "This is a short text",
        "Changed some things on the folder structure and added some functions to the convert.c file",
    ]; 

然后我的工具提示会显示一个html文本......

var tooltip = svg.append('foreignObject')
        .attr('x', 50)
        .attr('y', 50)
        .attr('width', 200)
        .attr('height', 300)
        .style("visibility", "hidden")
        .append("xhtml:body")
        .html('<div style="width: 150px;">Example</div>');

现在我想在for循环上创建我的圆圈,将数据附加到它们并让工具提示在鼠标悬停上显示正确的数据:

for (var i = 0; i < 4; i++) {

    svg.append("circle")
        .data(node[i])
        .attr("cx", 100*i+250)
        .attr("cy", 100)
        .attr("r", 10)
        .attr("fill", "steelblue" )
        .on("mouseover", function(d){
            return tooltip.style("visibility","visible")
                .html('<div style="width: 150px;">'+d+'</div>');
        }).on("mouseout", function(){
            return tooltip.style("visibility", "hidden");
        });
    }

但由于某种原因,当我将鼠标悬停在点上时,结果不是整个字符串,它只是字符串的第一个字符。我显然在这里遗漏了一些东西......

1 个答案:

答案 0 :(得分:2)

D3希望您提供一系列值,例如.data([1,2,3,4])。你正在传递字符串。因此,D3尝试将字符串的各个字符(因为字符串,就像数组一样,可以迭代)匹配到选择的元素。在这种情况下,已经存在一个元素,因此它将为其分配__data__属性,该属性等于字符串的第一个字符。其余字符将转到enter选项。

正如Lars Kotthoff在评论中提到的,使用D3时不应该使用for循环。相反,尝试这样的事情:

svg.selectAll('circle') // empty (yet) selection of circles
  .data(node) // apply data to the empty selection, where node is your array of strings
  .enter() // same as "for all entering (new) elements... "
    .append('circle') // creates as many circles as there are elements in node array
    .attr('cx', function (d, i) {
        // d is "Hello...", "foobarbaz", "This is a short text", etc.
        // i is 0, 1, 2, 3
        return 100 * i + 250; // dynamic, index-dependent x
    })
    .attr('cy', 100) // constant y value across all elements
    .on('mouseover', function (d) {
      console.log(d);
    });