D3.js — изменение узла графа направленной силы с круга на svg: rect

Я изменяю этот пример сворачиваемого иерархического макета сил, и у меня возникают проблемы с изменением узлы из кругов в квадраты (используя 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;
            }
        }

person cmckenzie    schedule 05.12.2013    source источник


Ответы (1)


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)

Элементы rect позиционируются путем установки положения их верхнего левый угол с x и y; Центры элементов circle устанавливаются с помощью cx и cy.

person Adam Pearce    schedule 05.12.2013
comment
Ой! Очень простое решение. Спасибо большое! Я понял, что это так, но я запутался между документацией D3 и SVG. - person cmckenzie; 05.12.2013