Javascript d3js Force Directed Graph-单击节点以弹出从JSON读取的信息框

Javascript d3js Force Directed Graph-单击节点以弹出从JSON读取的信息框,javascript,d3.js,force-layout,d3-force-directed,Javascript,D3.js,Force Layout,D3 Force Directed,我一直在使用D3js,但对D3js和Javascript还是新手 我希望能够单击节点和页面上的infobox弹出窗口,并打印有关该节点的一些信息(来自JSON) 我的json文件示例: {"directed": false, "graph": {}, "nodes": [{"id": 0, "name":"Ant" , "info":"Small Animal"}, {"id": 1 , "name":"Apple" , "info":"Fruit"}, {"id": 2 , "name"

我一直在使用D3js,但对D3js和Javascript还是新手

我希望能够单击节点和页面上的infobox弹出窗口,并打印有关该节点的一些信息(来自JSON)

我的json文件示例:

{"directed": false, "graph": {}, 
"nodes": [{"id": 0, "name":"Ant" , "info":"Small Animal"}, 
{"id": 1 , "name":"Apple" , "info":"Fruit"}, 
{"id": 2 , "name":"Bat" , "info":"Fly Animal"}, 
{"id": 3 , "name":"Boat" , "info":"Vehicle"}, 
{"id": 4 , "name":"Banana" , "info":"Long cute Fruit"}, 
{"id": 5 , "name":"Cat" , "info":"Best Animal"}], 

"links": [{"source": 0, "target": 0 , "weight":1}, {"source": 0, "target": 2, "weight": 0.3}, 
{"source": 0, "target": 5, "weight":0.8}, {"source": 1, "target": 1, "weight":1}, 
{"source": 1, "target": 4, "weight":0.5}, {"source": 2, "target": 2, "weight":1}, 
{"source": 3, "target": 3, "weight":1}, {"source": 4, "target": 4, "weight":1}, 
{"source": 5, "target": 5, "weight":1}], 
"multigraph": false}
所以当我点击一个节点时。它应该弹出如下内容:

Name: Ant
Info: Small Animal
Connected to: Bat with 0.3 weight , Cat with 0.8 weight

我的图形代码与我上面链接的力定向示例非常相似。

您可以使用
.on('click',function(d){})在节点上添加click事件
例如:

node.on("click", function(d){
      console.log(d);
       // here you can access data of node using d.key 
      alert("You clicked on node " + d.name);
    });

下面是一个快速实现,它使用SVG构建您的“信息盒”:

  var tip;
  node.on("click", function(d){
    if (tip) tip.remove();

    tip  = svg.append("g")
      .attr("transform", "translate(" + d.x  + "," + d.y + ")");

    var rect = tip.append("rect")
      .style("fill", "white")
      .style("stroke", "steelblue");

    tip.append("text")
      .text("Name: " + d.name)
      .attr("dy", "1em")
      .attr("x", 5);

    tip.append("text")
      .text("Info: " + d.info)
      .attr("dy", "2em")
      .attr("x", 5);

    var con = graph.links
      .filter(function(d1){
        return d1.source.id === d.id;
      })
      .map(function(d1){
        return d1.target.name + " with weight " + d1.weight;
      })

    tip.append("text")
      .text("Connected to: " + con.join(","))
      .attr("dy", "3em")
      .attr("x", 5);

    var bbox = tip.node().getBBox();
    rect.attr("width", bbox.width + 5)
        .attr("height", bbox.height + 5)
  });
运行代码:


.连接线{
行程:#999;
笔划不透明度:0.6;
}
.节点圆{
冲程:#fff;
笔划宽度:1.5px;
}
正文{
字体系列:无衬线;
}
var svg=d3。选择(“svg”),
宽度=+svg.attr(“宽度”),
高度=+svg.attr(“高度”);
var color=d3.scaleOrdinal(d3.schemeCategory 20);
var simulation=d3.forceSimulation()
.force(“link”,d3.forceLink().id(函数(d){return d.id;}))
.force(“电荷”,d3.forceManyBody())
.力(“中心”,d3.力中心(宽度/2,高度/2));
d3.json(“https://jsonblob.com/api/15daa79f-7573-11e8-b9d7-1b0997147957,函数(错误,图形){
如果(错误)抛出错误;
link=svg.append(“g”)
.attr(“类”、“链接”)
.selectAll(“行”)
.数据(图表.链接)
.enter().append(“行”)
.attr(“笔划宽度”,函数(d){返回d.weight*3;});
var node=svg.append(“g”)
.attr(“类”、“节点”)
.selectAll(“圆圈”)
.数据(图.节点)
.enter().append(“圆”)
.attr(“r”,5)
.attr(“fill”,函数(d){返回颜色(d.group);})
.call(d3.drag()
.on(“开始”,拖动开始)
.打开(“拖动”,拖动)
。在(“结束”,dragended));
var-tip;
打开(“单击”,函数(){
如果(tip)tip.remove();
});
节点上(“单击”,功能(d){
d3.event.stopPropagation();
如果(tip)tip.remove();
tip=svg.append(“g”)
.attr(“转换”、“转换”(+d.x+)、“+d.y+”);
var rect=tip.append(“rect”)
.样式(“填充”、“白色”)
.风格(“笔划”、“钢蓝”);
提示:追加(“文本”)
.text(“名称:”+d.Name)
.attr(“dy”、“1em”)
.attr(“x”,5);
提示:追加(“文本”)
.text(“信息:+d.Info”)
.attr(“dy”,“2em”)
.attr(“x”,5);
var con=graph.links
.过滤器(功能(d1){
返回d1.source.id==d.id;
})
.地图(功能(d1){
返回d1.target.name+“带权重”+d1.weight;
})
提示:追加(“文本”)
.text(“连接到:”+con.join(“,”))
.attr(“dy”、“3em”)
.attr(“x”,5);
var bbox=tip.node().getBBox();
矩形属性(“宽度”,bbox.width+5)
.attr(“高度”,bbox.height+5)
});
模拟
.nodes(图.nodes)
。在(勾选)上;
模拟力(“链接”)
.links(图形链接);
函数勾选(){
链接
.attr(“x1”,函数(d){返回d.source.x;})
.attr(“y1”,函数(d){返回d.source.y;})
.attr(“x2”,函数(d){返回d.target.x;})
.attr(“y2”,函数(d){返回d.target.y;});
节点
.attr(“cx”,函数(d){return d.x;})
.attr(“cy”,函数(d){返回d.y;});
}
});
函数dragstarted(d){
如果(!d3.event.active)simulation.alphaTarget(0.3.restart();
d、 fx=d.x;
d、 fy=d.y;
}
函数(d){
d、 fx=d3.event.x;
d、 fy=d3.event.y;
}
函数d(d){
如果(!d3.event.active)simulation.alphaTarget(0);
d、 fx=null;
d、 fy=null;
}

非常感谢您。它看起来真的很好,但当信息显示时,没有办法删除它(除了单击其他节点)。点击空白时信息框会消失吗?谢谢你的帮助@马克:当我在chrome中运行这个程序时,我得到一个错误:{“消息”:“Uncaught[object ProgressEvent]”,“filename”:“lineno”:46,“colno”:14}@SethRobertson,已修复。@Mark:fixed?我和Seth Robertson犯了同样的错误