如何显示被点击目标的源节点?

时间:2015-10-27 08:12:14

标签: javascript d3.js force-layout

如何使用D3?

在强制有向图中显示所单击目标节点的源节点名称?

以下代码段来自某些example code for directed graphs by Mike Bostock。如何修改此基本代码,以便在图表上单击节点时,该节点的目标值将显示在屏幕上(在这种情况下,我想显示name属性)?

例如"nodes"中的第0个元素是:

"nodes":[
  {"name":"Myriel","group":1},
  ...
]

"links"中,目标定义如下:

"links":[
  {"source":1,"target":0,"value":1},        // Napoleon
  {"source":2,"target":0,"value":8},        // Mlle.Baptistine
  {"source":3,"target":0,"value":10},       // Mme.Magloire
  {"source":3,"target":2,"value":6},
  {"source":4,"target":0,"value":1},        // CountessdeLo
  {"source":5,"target":0,"value":1},        // Geborand
  {"source":6,"target":0,"value":1},        // Champtercier
  {"source":7,"target":0,"value":1},        // Cravatte
  {"source":8,"target":0,"value":2},        // Count
  {"source":9,"target":0,"value":1},        // OldMan
  ...
  {"source":11,"target":0,"value":5},       // Valjean
  ...
]

然后点击节点Myriel将显示:

  

拿破仑,Mlle.Baptistine,Mme.Magloire,CountessdeLo,Geborand,尚普泰尔谢,CRAVATTE,计数,OLDMAN,瓦吉恩

Myriel位于图表中:

enter image description here

以下是JavaScript代码:

var width = 960,
    height = 500;
var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);
var color = d3.scale.category20();
var force = d3.layout.force()
    .charge(-120)
    .linkDistance(30)
    .size([width, height]);
d3.json("https://gist.githubusercontent.com/mbostock/4062045/raw/9653f99dbf6050b0f28ceafbba659ac5e1e66fbd/miserables.json", function(error, graph) {
  if (error) throw error;
  force
      .nodes(graph.nodes)
      .links(graph.links)
      .start();
  var link = svg.selectAll(".link")
      .data(graph.links)
    .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });
  var node = svg.selectAll(".node")
      .data(graph.nodes)
    .enter().append("circle")
      .attr("class", "node")
      .attr("r", 5)
      .style("fill", function(d) { return color(d.group); })
      .call(force.drag)
      .on("click",function(d){ 
        var targets = graph.links.filter(function(i){
          return i.target.name == d.name
        });
        tip.show( targets.map(function(i){ return i.source.name;}) );

      });
  node.append("title")
      .text(function(d) { return d.name; });
  force.on("tick", function() {
    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });
    node.attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
  });
});

var width = 960,
    height = 500;
var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);
var color = d3.scale.category20();
var force = d3.layout.force()
    .charge(-120)
    .linkDistance(30)
    .size([width, height]);
d3.json("https://gist.githubusercontent.com/mbostock/4062045/raw/9653f99dbf6050b0f28ceafbba659ac5e1e66fbd/miserables.json", function(error, graph) {
  if (error) throw error;
  force
      .nodes(graph.nodes)
      .links(graph.links)
      .start();
  var link = svg.selectAll(".link")
      .data(graph.links)
    .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });
  var node = svg.selectAll(".node")
      .data(graph.nodes)
    .enter().append("circle")
      .attr("class", "node")
      .attr("r", 5)
      .style("fill", function(d) { return color(d.group); })
      .call(force.drag)
      .on("click",function(d){ 
        var targets = graph.links.filter(function(i){
          return i.target.name == d.name
        });
        tip.show( targets.map(function(i){ return i.source.name;}) );
        
      });
  node.append("title")
      .text(function(d) { return d.name; });
  force.on("tick", function() {
    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });
    node.attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
  });
});
.node {
  stroke: #fff;
  stroke-width: 1.5px;
}
.link {
  stroke: #999;
  stroke-opacity: .6;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.0/d3.min.js"></script>

1 个答案:

答案 0 :(得分:2)

在每个节点上添加点击事件,然后在里面我们可以通过过滤targets数组来获取所有graph.links,这样我们只有target.named.name相同的元素单击节点名称.map()。完成后,您可以使用.source.name返回包含name的数组,以便在targets中提供这些项目的 .on("click",function(d) { var targets = graph.links.filter(function(i){ return i.target.name==d.name; }); tip.show( targets.map(function(i){ return i.source.name; }) ); });

var tip = d3.tip().attr('class', 'd3-tip').html(function(d) { return d; });

var width = 960,
    height = 500;
var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

svg.call(tip);

var color = d3.scale.category20();
var force = d3.layout.force()
    .charge(-120)
    .linkDistance(30)
    .size([width, height]);
d3.json("https://gist.githubusercontent.com/mbostock/4062045/raw/9653f99dbf6050b0f28ceafbba659ac5e1e66fbd/miserables.json", function(error, graph) {
  if (error) throw error;
  force
      .nodes(graph.nodes)
      .links(graph.links)
      .start();
  var link = svg.selectAll(".link")
      .data(graph.links)
    .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(d.value); });
  var node = svg.selectAll(".node")
      .data(graph.nodes)
    .enter().append("circle")
      .attr("class", "node")
      .attr("r", 5)
      .style("fill", function(d) { return color(d.group); })
      .call(force.drag)
      .on("click",function(d){ 
        var targets = graph.links.filter(function(i){
          return i.target.name == d.name
        });
        tip.show( targets.map(function(i){ return i.source.name;}) );
        
      });
  node.append("title")
      .text(function(d) { return d.name; });
  force.on("tick", function() {
    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });
    node.attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
  });
});

.node {
  stroke: #fff;
  stroke-width: 1.5px;
}
.link {
  stroke: #999;
  stroke-opacity: .6;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.6.7/d3-tip.min.js"></script>
var tip = d3.tip().attr('class', 'd3-tip').html(function(d) { return d; });
...
var svg = ..
svg.call(tip);

现在,为了便于显示这些值,可以使用d3-tip库。这将初始化为图形,如下所示:

tip.show(...)

最后,第一个代码段中的if (a & 1){ ... } 函数会在图表上显示这些项目。