【问题标题】:How to display source nodes of a clicked target?如何显示点击目标的源节点?
【发布时间】:2016-01-26 13:19:42
【问题描述】:

如何使用 D3 在强制有向图中显示单击目标节点的源节点名称?

下面的sn-p来自一些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会显示:

拿破仑、巴普蒂斯汀夫人、马格洛瓦夫人、伯爵夫人、格伯朗、尚普特谢、克拉瓦特、伯爵、老人、冉阿让

Myriel 在图中位于此处:

以下是 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>

【问题讨论】:

  • 注意: 用户发布了这样一个问题,我认为其中的答案对网站很有价值。尽管用户在我能够发布我的解决方案之前删除了他们的问题。因此,我用其他信息重新创建了这个问题,以便我可以分享我的答案。欢迎其他答案。

标签: javascript d3.js force-layout


【解决方案1】:

在每个节点上添加一个点击事件,然后在里面我们可以通过过滤graph.links数组得到所有的targets,这样我们就只有target.name与点击节点名称d.name相同的元素.一旦我们有了,您就可以使用.map() 返回带有.source.name 的数组,以在targets 中提供这些项目的name

  .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>

现在可以使用d3-tip 库轻松显示这些值。这将像这样为图形初始化:

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

最后,第一个代码 sn-p 中的 tip.show(...) 函数将在图表上显示这些项目。

【讨论】:

    猜你喜欢
    • 2016-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-04
    • 2021-12-11
    • 2018-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多