D3:当我修改代码以通过定义的键而不是索引链接节点时,强制布局图中不显示链接

时间:2014-03-18 19:33:33

标签: graph d3.js force-layout

我正在使用mbostock的Mobile Patent Suit

我通过定义的键(名称和类型)而不是索引来修改数据格式以链接节点。我已经尝试修改tick函数并选择和追加,但似乎没有任何效果。

这是我在JsFiddle

上的代码
<!DOCTYPE html>
<meta charset="utf-8">
<style>

.node circle {
  /*stroke: #fff;*/
  cursor: pointer;
  stroke: #3182bd;
  stroke-width: 1.5px;
}

.node text {
  font: 10px sans-serif;
  pointer-events: none;
  text-anchor: middle;
}

.link {
  stroke-opacity: .6;
  stroke-width: 1.5px;
  stroke: #666;
  fill: none;
}

.link.deliverFor {
  stroke: green;
}

.link.sentTo {
  stroke-dasharray: 0,2 1;
}

/* color of nodes based on type */
circle.emailAddress {
  fill: blue;
}

circle.ip {
  fill: red;
}

circle.missing {
  fill: "#3182bd";
}

</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>

var width = 960,
    height = 500;

var color = d3.scale.category20();

var linkDistanceScale = d3.scale.linear()
      .domain([10, 5000])
      .range([2, 300])
      .clamp(true);

var force = d3.layout.force()
    .linkDistance(30)
    .charge(-120)
    .size([width, height]);

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

var graph = {
    "nodes": [
        {
            "name": "foo@pp.com",
            "type": "emailAddress",
            "size": 1234
        },
        {
            "name": "192.168.0.1",
            "type": "ip",
            "size": 870
        },
        {
            "name": "bar@pp.com",
            "type": "emailAddress",
            "size": 3423
        }
    ],
    "undirectedNeighbors": [
        {
            "label": "deliverFor",
            "left": {
                "name": "foo@pp.com",
                "type": "emailAddress"
            },
            "right": {
                "name": "192.168.0.1",
                "type": "ip"
            },
            "weight": 366
        },
        {
            "left": {
                "type": "emailAddress",
                "name": "foo@pp.com"
            },
            "right": {
                "type": "emailAddress",
                "name": "bar@pp.com"
            },
            "label": "sentTo",
            "weight": 777
        }
    ]
};

  var my_nodes = graph.nodes.slice(),
      my_neighbors = graph.undirectedNeighbors.slice();

  console.log("my_neighbors", my_neighbors);

  var hash_lookup = [];

  // make it so we can lookup nodes by entry (name: x, type, y) in O(1):
  my_nodes.forEach( function(node) {
      var key = {name: node.name, type: node.type};
      hash_lookup[key] = node;
  });

  // tell d3 where to find nodes info
  my_neighbors.forEach( function(link) {

      var left = link.left;
      var right = link.right; 

      var leftKey = {name: left.name, type: left.type};
      var rightKey = {name: right.name, type: right.type};

      link.source = hash_lookup[leftKey];
      link.target = hash_lookup[rightKey];
  });

  console.log("my_neighbors", my_neighbors);
  console.log("my_nodes", my_nodes);

  console.log("neighobrs", graph.undirectedNeighbors);

/************** SETUP FORCE LAYOUT ****************/

  force
      .nodes(my_nodes)
      .links(my_neighbors)
      .linkDistance( function(d) {
          console.log("linkDistance", d);
          return linkDistanceScale(d.weight);
      })
      .start();

console.log("force.links()", force.links());
/************** DRAW PATHS ****************/

  var link = svg
      .append("svg:g")   // the "curves" is drawn inside this container
      .selectAll("path")
      .data(force.links())
      .enter()
      .append("svg:path")
      // .attr("class", "link")
      .attr("class", function(d) { 
          return "link " + d.type; 
      });


  /************** DRAW CIRCLES ****************/
  var node = svg
      .selectAll(".node")
      .data(force.nodes());

  var circle = node
      .enter()
      .append("circle")
      .attr("class", "node")
      .attr("r", function(d) { 
          console.log("circle d", d);
          return Math.sqrt(d.size) / 10 || 4.5; 
      })
      .attr("class", function(d) {
          return d.type || "missing";     // color circle based on circl.* defined above
      })
      .call(force.drag);

  /************** DISPLAY NAME WHEN CURVER HOVER OVER CIRCLE  ****************/
  var text = circle.append("title")
      .text(function(d) { return d.name; });

  force.on("tick", function() {
      link.attr("d", function(d) {
        var dx = d.target.x - d.source.x,
            dy = d.target.y - d.source.y,
            dr = Math.sqrt(dx * dx + dy * dy);

        return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;

      });

      node
        .attr("transform", function(d) { 
            return "translate(" + d.x + "," + d.y + ")"; });
  });


</script>

非常感谢任何见解。

1 个答案:

答案 0 :(得分:0)

不管这种方法是否是一个好主意,问题在于你试图将对象用作对象中的键(你的hash_lookup)。这不是适用于JavaScript的东西。快速,肮脏的黑客修复只是在使用它们之前将地图键转换为字符串

var hash_lookup = {};

// make it so we can lookup nodes by entry (name: x, type, y) in O(1):
my_nodes.forEach( function(node) {
  var key = JSON.stringify({name: node.name, type: node.type});
  hash_lookup[key] = node;
});

// tell d3 where to find nodes info
my_neighbors.forEach( function(link) {

  var left = link.left;
  var right = link.right; 

  var leftKey = JSON.stringify({name: left.name, type: left.type});
  var rightKey = JSON.stringify({name: right.name, type: right.type});

  link.source = hash_lookup[leftKey];
  link.target = hash_lookup[rightKey];
});