javascript - D3 Cluster Force add group-nested circle -


i trying add group-nested circle clusters on mouse click event, to obtain html markup this.

but newly added circles go on top of existent ones , initial cluster gravity lost. want newly added elements behave same way initial ones. have tried modify logic on function mousedown() not obtained desired behavior. guidance highly appreciated.

here current code:

    var width = window.innerwidth,              height = window.innerheight,              padding = 1.5,      // separation between same-color circles              clusterpadding = 6, // separation between different-color circles              maxradius = 60,              minradius = 20;        var n = 3, // intitotal number of circles          m = 2; // number of distinct clusters        var color = d3.scale.category10()          .domain(d3.range(m));        // largest node each cluster.      var clusters = new array(m);         // data circles      var nodes = d3.range(n).map(function () {          var = math.floor(math.random() * m),              r = math.sqrt((i + 1) / m * -math.log(math.random())) * maxradius,              nodeid = r.tostring(),              d = { cluster: i, radius: r, nodeid:nodeid};          if (!clusters[i] || (r > clusters[i].radius)) clusters[i] = d;          return d;      });        var force = d3.layout.force()          .nodes(nodes)          .size([width, height])          .gravity(.02)          .charge(0)          .on("tick", tick)          .start();        var svg = d3.select("body").append("svg")          .attr("width", width)          .attr("height", height)          .on("mousedown", mousedown);        var group = svg.selectall("g")          .data(nodes)          .enter().append("g")                  .attr("class", "node")          .call(force.drag);        var circle = group.append("circle")          .attr("r", function (d) { return d.radius; })          .attr("fill", function (d) { return color(d.cluster); });        function mousedown() {            var = math.floor(math.random() * m),          r = math.sqrt((i + 1) / m * -math.log(math.random())) * maxradius,          nodeid = r.tostring(),          d = { cluster: i, radius: r, nodeid: nodeid};          if (!clusters[i] || (r > clusters[i].radius)) clusters[i] = d;          nodes.push(d);                    group = svg.selectall("g")              .data(nodes)              .enter().append("g")              .attr("class", "node")              .call(force.drag);            circle = group.append("circle")              .attr("r", function (d) { return d.radius; })          	.attr("fill", function (d) { return color(d.cluster); });            force.start();      };        function tick(e) {          circle              .each(cluster(10 * e.alpha * e.alpha))              .each(collide(.5))              .attr("cx", function (d) { return d.x; })              .attr("cy", function (d) { return d.y; });      }        // move d adjacent cluster node.      function cluster(alpha) {          return function (d) {              var cluster = clusters[d.cluster];              if (cluster === d) return;              var x = d.x - cluster.x,                  y = d.y - cluster.y,                  l = math.sqrt(x * x + y * y),                  r = d.radius + cluster.radius;              if (l != r) {                  l = (l - r) / l * alpha;                  d.x -= x *= l;                  d.y -= y *= l;                  cluster.x += x;                  cluster.y += y;              }          };      }        // resolves collisions between d , other circles.      function collide(alpha) {          var quadtree = d3.geom.quadtree(nodes);          return function (d) {              var r = d.radius + maxradius + math.max(padding, clusterpadding),                  nx1 = d.x - r,                  nx2 = d.x + r,                  ny1 = d.y - r,                  ny2 = d.y + r;              quadtree.visit(function (quad, x1, y1, x2, y2) {                  if (quad.point && (quad.point !== d)) {                      var x = d.x - quad.point.x,                          y = d.y - quad.point.y,                          l = math.sqrt(x * x + y * y),                          r = d.radius + quad.point.radius + (d.cluster === quad.point.cluster ? padding : clusterpadding);                      if (l < r) {                          l = (l - r) / l * alpha;                          d.x -= x *= l;                          d.y -= y *= l;                          quad.point.x += x;                          quad.point.y += y;                      }                  }                  return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;              });          };      }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>


Comments

Popular posts from this blog

asynchronous - C# WinSCP .NET assembly: How to upload multiple files asynchronously -

aws api gateway - SerializationException in posting new Records via Dynamodb Proxy Service in API -

asp.net - Problems sending emails from forum -