D3.js - 将力导向图节点从圆改变为svg:rect

时间:2013-12-05 03:48:45

标签: javascript svg d3.js force-layout

我正在修改this可折叠的分层力布局示例,我无法将节点从圆圈更改为方块(使用svg:rect)。使用我当前的代码,所有方块都显示在左上角。否则它们表现得相对正常(我可以点击它们来展开/折叠树)。

这是我用于此功能和其他功能的CSS样式:

    .node {
      cursor: pointer;
    }
    .node rect {
      fill: skyblue;
      stroke: green;
      stroke-width: 1.5px;
    }
    .node text {
      font: 10px sans-serif;
    }
    .link {
      fill: none;
      stroke: green;
      stroke-width: 1.5px;
    }
    #container div{
      float:left;
    }
    .chartSpace div{
      float:left;
      margin-right:screen.width-960px;
    }

以下是力布局的代码:

function forceDirected(){
            //Clear SVG
            d3.select("svg").remove();

            var width = 960,
                height = 500,
                root;

            var force = d3.layout.force()
                .size([width, height])
                .on("tick", tick);

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

            var link = svg.selectAll(".link"),
                node = svg.selectAll(".node");

            d3.json("flare.json", function(flare) {
              root = flare;
              update();
            });

            function update() {
              var nodes = flatten(root),
                  links = d3.layout.tree().links(nodes);

              // Restart the force layout.
              force
                  .nodes(nodes)
                  .links(links)
                  .start();

              // Update the links…
              link = link.data(links, function(d) { return d.target.id; });

              // Exit any old links.
              link.exit().remove();

              // Enter any new links.
              link.enter().insert("line", ".node")
                  .attr("class", "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; });

              // Update the nodes…
              node = node.data(nodes, function(d) { return d.id; }).style("fill", color);

              // Exit any old nodes.
              node.exit().remove();

              // Enter any new nodes.
              node.enter().append("svg:rect")
                  .attr("class","node")
                  .attr("cx", function(d) { return d.x; })
                  .attr("cy", function(d) { return d.y; })
                  .attr("width", "6")
                  .attr("height", "6")
                  .on("click", click)
                  .call(force.drag);
            }

            function tick() {
              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; });
            }

            // Stroke colors
            function strColor(d) {
              return d._children ? "green" : d.children ? "green" : "green";
            }

            // Node colors
            function color(d) {
              return d._children ? "skyblue" : d.children ? "skyblue" : "skyblue";
            }

            // Toggle children on click.
            function click(d) {
              if (!d3.event.defaultPrevented) {
                if (d.children) {
                  d._children = d.children;
                  d.children = null;
                } else {
                  d.children = d._children;
                  d._children = null;
                }
                update();
              }
            }

            // Returns a list of all nodes under the root.
            function flatten(root) {
              var nodes = [], i = 0;

              function recurse(node) {
                if (node.children) node.children.forEach(recurse);
                if (!node.id) node.id = ++i;
                nodes.push(node);
              }

              recurse(root);
              return nodes;
            }
        }

1 个答案:

答案 0 :(得分:2)

node.enter().append("svg:rect")
  .attr("class","node")
  .attr("cx", function(d) { return d.x; })
  .attr("cy", function(d) { return d.y; })

应该是

var rectSize = 6;
node.enter().append("svg:rect")
  .attr("class","node")
  .attr("x", function(d) { return d.x + rectSize/2; })
  .attr("y", function(d) { return d.y + rectSize/2; })
  .attr("width", rectSize)
  .attr("height", rectSize)
通过使用xy设置左上角的位置来定位

rect个元素。 circle元素中心设置为cxcy