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

Populating a select list of connected nodes in d3.js

本文关键字:节点 选择 列表 连接 d3 js 填充      更新时间:2023-09-26
在这个

美妙的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;
    });
}

请指出我的错误。谢谢。

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

你需要在节点组成中有一个类似的东西:

// 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);
       }
   });
 });

美上帝。在雨果·拉斯蒂科特的帮助下,我找到了答案。我不得不修改一些东西,这是我的"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展示了如何在列表中附加它。谢谢。