如何使用d3.js更改圆圈样式

时间:2012-11-13 13:02:02

标签: d3.js force-layout

我正在尝试更改d3.js中内置强制定向的http://bl.ocks.org/1153292示例。

我想根据Json中的类型为圆创建类。 我将需要使用CSS,但我不知道如何更改代码以应用它。

这是我到目前为止修改的代码....

  <!DOCTYPE html>
  <html>
    <head>
      <meta http-equiv="Content-type" content="text/html; charset=utf-8">
      <title>Mobile Patent Suits</title>
      <script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.29.1"></script>
      <script type="text/javascript" src="http://mbostock.github.com/d3/d3.geom.js?1.29.1"></script>
      <script type="text/javascript" src="http://mbostock.github.com/d3/d3.layout.js?1.29.1"></script>
      <style type="text/css">

  circle {
    fill: #ccc;
    stroke: #333;
    stroke-width: 1.5px;
  }

  text {
    font: 10px sans-serif;
    pointer-events: none;
  }

  text.shadow {
    stroke: #fff;
    stroke-width: 3px;
    stroke-opacity: .8;
  }

      </style>
    </head>
    <body>
      <script type="text/javascript">

  // http://blog.thomsonreuters.com/index.php/mobile-patent-suits-graphic-of-the-day/
  var links = [
    {source: "t1", target: "hate", type: "green"},
    {source: "t1", target: "good", type: "green"},
    {source: "t2", target: "hate", type: "green"},
    {source: "t3", target: "good", type: "green"},
    {source: "t4", target: "good", type: "green"},
    {source: "hate", target: "airport", type: "yellow"},
    {source: "good", target: "airport", type: "yellow"},
    {source: "good", target: "flight", type: "yellow"},
  ];

  var nodes = {};

  // Compute the distinct nodes from the links.
  links.forEach(function(link) {
    link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
    link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
  });

  var w = 960,
      h = 500;

  var force = d3.layout.force()
      .nodes(d3.values(nodes))
      .links(links)
      .size([w, h])
      .linkDistance(60)
      .charge(-300)
      .on("tick", tick)
      .start();

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

  var path = svg.append("svg:g").selectAll("path")
      .data(force.links())
    .enter().append("svg:path")
      .attr("class", function(d) { return "link " + d.type; })
      .attr("marker-end", function(d) { return "url(#" + d.type + ")"; });

  var circle = svg.append("svg:g").selectAll("circle")
      .data(force.nodes())
    .enter().append("svg:circle")
      .attr("r", 6)
      .call(force.drag);

  var text = svg.append("svg:g").selectAll("g")
      .data(force.nodes())
    .enter().append("svg:g");

  // A copy of the text with a thick white stroke for legibility.
  text.append("svg:text")
      .attr("x", 8)
      .attr("y", ".31em")
      .attr("class", "shadow")
      .text(function(d) { return d.name; });

  text.append("svg:text")
      .attr("x", 8)
      .attr("y", ".31em")
      .text(function(d) { return d.name; });

  // Use elliptical arc path segments to doubly-encode directionality.
  function tick() {
    path.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;
    });

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

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

      </script>
    </body>
  </html>

有人可以给我一个提示吗? 感谢

1 个答案:

答案 0 :(得分:3)

您有一组连接links。然后,您可以通过以下行从此数组中提取不同的节点:

  links.forEach(function(link) {
    link.source = nodes[link.source] || (nodes[link.source] = {name: link.source} );
    link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
  });

此时,您应为每个节点插入type。所以,例如对于这个节点,我们可以使用链接的类(但是,在这种情况下,节点的所有链接中只有一个确定它的类)。这将导致以下代码:

 links.forEach(function(link) {
    link.source = nodes[link.source] || (nodes[link.source] = {name: link.source, type: link.type} );
    link.target = nodes[link.target] || (nodes[link.target] = {name: link.target, type: link.type});
  });

并非所有节点都具有type属性,而不仅仅是name

稍后在此处创建圈子

  var circle = svg.append("svg:g").selectAll("circle")
      .data( force.nodes() )
    .enter().append("svg:circle")
      .attr("r", 6)
      .call(force.drag);

我们可以将该type属性与确定每个circle类的函数一起使用,如下所示:

  var circle = svg.append("svg:g").selectAll("circle")
      .data( force.nodes() )
    .enter().append("svg:circle")
      .attr("r", 6)
      .attr( 'class', function( d ) { console.log( d ); return d.type; } )
      .call(force.drag);

现在所有圈子都有各自的班级。

请注意,您可能希望确定每个节点的类型有所不同,然后在此示例中。因此,相应地更改links.forEach( ... );中的上述声明。