在d3.js中填充已连接节点的选择列表

时间:2016-02-18 04:38:07

标签: javascript d3.js

这个精彩的d3仍然是一个菜鸟,并且在使用它时遇到了困难。请理解我不是程序员,我正在考虑自己的兴趣。因此,我将感谢外行解释。

我创建了一个d3力布局。我正在寻找一个动态填充连接节点的“选择”下拉列表的解决方案。即,如果用户单击节点或从第一个下拉列表中选择,则会显示另一个“选择”下拉列表,其中包含已连接节点的列表。

这是我不成功的方法。

    var node = svg.selectAll(".node")
                  .data(graph.nodes);

    node.enter().append("g")
        .attr("class", "node")
        .attr("r", function(d) { return d.size; })
        .attr("class", function(d) { return "node _" + d.size; })
        .attr("id", function (d) { return "n" + d.code ; })
        .style("fill", function (d) { return color(d.group); })
        .on("mouseover", function(d) { highlight(d); })
        .on("mouseout", mouseout)
        .on('click', populate)
        .call(force.drag)
        ;

  var linkedByIndex = {};
    graph.links.forEach(function (d, i) {
        graph.links[i].source = graph.nodes.indexOf(graph.links[i].source);
        graph.links[i].target = graph.nodes.indexOf(graph.links[i].target);
        linkedByIndex[graph.links[i].source + "," + graph.links[i].target] = 1 ;
        });

    function isConnected(a, b) {
    return linkedByIndex[a.index + "," + b.index] || linkedByIndex[b.index + "," + a.index] || a.index == b.index;
    }

var select = d3.select("#search1") //first 'select' drop-down list//
    .append("select")
    .on('change.pcp', populate);

  select.selectAll("option")
    .data(graph.nodes.filter(function(d){return d.sel == "1";}))
    .enter()
    .append("option")
    .attr("value", function(d) {return d.code ;})
    .text(function(d) {return d.name ;});

   var select7 = d3.select("#viewList") //second 'select' drop-down list//
    .append("select")
    .on('change.sn', searchNode)
    ;

  select7.selectAll("option")
    .data(graph.nodes.filter(function (d){populate (d) ;}))
    .enter()
    .append("option")
    .attr("value", function(d) {return d.code ;})
    .text(function(d) {return d.name ;});

然后我的功能如下

function populate() { 
    name=[];
    var selectedVal = d3.event.target.value;
    //iterate through all the nodes
    graph.nodes.every(function(n){
      if (n.code == selectedVal){
        var d = n;
        d3.selectAll(".node")
            .data(nodeArray, filter(function (o) { 
                thisList = isConnected(d,o) ? 1: name;
                return thisList;
            }));
            return false;
        }
        return true;
    });
}

请指出我的错误。谢谢。

2 个答案:

答案 0 :(得分:1)

如果您没有更改链接和节点的结构,则此解决方案应该可以正常工作。

您需要在节点组合中使用类似的东西:

// On click on the node
node.on('click',function(d) {
  // Iterate throw the links
  graph.links.forEach(function (l, i) {
       if (d === l.source )
       {
          console.log(l.target);
          d3.select("#list").append("p").text(l.target.name);
       }
       if (d === l.target )
       {
          console.log(l.source);
          d3.select("#list").append("p").text(l.source.name);
       }
   });

 });

答案 1 :(得分:0)

赞美上帝。我在HugoLasticot的帮助下找到了答案。我不得不修改一些我的“isConnected”功能。我知道我必须利用这个功能,但只是不知道如何。经过几次试验和错误后,我设法找到了解决方案。我使用HugoLasticot的方式“将连接附加到列表中”。非常感谢你。无论如何,我创建了另一个“isConnected”函数,它被称为“isConnected1”,专门用于此目的。它看起来像这样。

    function isConnected1(a, b) {
    return linkedByIndex[a.index + "," + b.index] || linkedByIndex[b.index + "," + a.index];
    }

这与isConnected函数有关,因为它不会返回当前单击的节点。

        .on('click',function(d) {
              // Iterate throw the links
              graph.nodes.forEach(function (l) {
                   if (isConnected1 (d, l) == 1)
                   {
                      // Append your nodes to a list
                       d3.select("#viewList").append("option").text(l.name);
                   }
               });

             })

HugoLasticot代码的缺点是它返回被点击的节点名称而不是连接的名称。 “.text(d.name)”中的注意事项特定于单击的节点。即使我们在forEach函数中执行了此操作,它也只会返回该特定节点。所以我改写了“.text(l.name)”,以便缩小“d.name”以外的范围。

我仍然是d3的新手,因此我的解释有困难,英语不是我的主要语言。我希望这个解决方案对有类似困难的人有益。我还必须给HugoLasticot提供学分,以显示如何将其添加到列表中。谢谢。