【问题标题】:Recreate Cluster Force Layout using d3 v4.0使用 d3 v4.0 重新创建集群强制布局
【发布时间】:2016-07-14 07:09:19
【问题描述】:

我试图使用 D3 v4 重新创建集群强制布局,如下所示:https://bl.ocks.org/mbostock/1747543。我重用了 Mike 代码中的集群功能,但结果并不好(http://codepen.io/aizizhang/pen/OXzJdK)。另外,如果我传入一个大于 1 的 alpha 参数,cx 和 cy 将无法正确计算。有人可以帮帮我吗?

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Clustered Bubble Chart</title>
  <script src="https://d3js.org/d3.v4.js"></script>
</head>

<body>
  <script>
    let margin = {
        top: 100,
        right: 100,
        bottom: 100,
        left: 100
      },
      height = window.innerHeight,
      width = window.innerWidth,
      padding = 1.5, // separation between same-color nodes
      clusterPadding = 6, // separation between different-color nodes
      maxRadius = 12,
      n = 200, // total number of nodes
      m = 10, // number of distinct clusters
      z = d3.scaleOrdinal(d3.schemeCategory20),
      clusters = new Array(m);

    let svg = d3.select('body')
      .append('svg')
      .attr('height', height)
      .attr('width', width)
      .append('g').attr('transform', `translate(${margin.right}, ${margin.top})`);
    let nodes = d3.range(200).map(() => {
      let i = Math.floor(Math.random() * m),
        radius = Math.sqrt((i + 1) / m * -Math.log(Math.random())) * maxRadius,
        d = {
          cluster: i,
          r: radius,
          x: Math.random() * 200,
          y: Math.random() * 200
        };
      if (!clusters[i] || (radius > clusters[i].r)) clusters[i] = d;
      return d;
    });

    let circles = svg.append('g')
      .datum(nodes)
      .selectAll('.circle')
      .data(d => d)
      .enter().append('circle')
      .attr('r', (d) => d.r)
      .attr('cx', (d) => d.x)
      .attr('cy', (d) => d.y)
      .attr('fill', (d) => z(d.cluster))
      .attr('stroke', 'black')
      .attr('stroke-width', 1);

    let simulation = d3.forceSimulation(nodes)
      .velocityDecay(0.2)
      .force("x", d3.forceX().x(200).strength(.5))
      .force("y", d3.forceY().y(200).strength(.5))
      .force("collide", d3.forceCollide().radius(function(d) {
        return d.r + 0.5;
      }).strength(0.5).iterations(2))
      .on("tick", ticked)
      // .force("charge", d3.forceManyBody(100))

    function ticked() {

      // let alpha = simulation.alpha();
      circles
        .each(clustering(0.5))
        .attr('cx', (d) => d.x)
        .attr('cy', (d) => d.y);
    }

     // Move d to be adjacent to the cluster node.
    function clustering(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.r + cluster.r;
        if (l !== r) {
          l = (l - r) / l * alpha;
          d.x -= x *= l;
          d.y -= y *= l;
          cluster.x += x;
          cluster.y += y;
        }
      };
    }
  </script>
</body>

</html>

【问题讨论】:

    标签: d3.js


    【解决方案1】:

    我认为部分问题是您正在使用新的 4.0 碰撞力,但您需要使用您正在复制的原始块的碰撞计算。这是原始示例的一个端口:

    http://bl.ocks.org/shancarter/f621ac5d93498aa1223d8d20e5d3a0f4

    希望有帮助!

    【讨论】:

      猜你喜欢
      • 2016-03-11
      • 2016-01-28
      • 1970-01-01
      • 2013-08-14
      • 2013-05-04
      • 2014-10-18
      • 2015-05-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多