【问题标题】:d3.js forceSimulation() with object entriesd3.js forceSimulation() 与对象条目
【发布时间】:2018-02-22 18:34:49
【问题描述】:


我的气泡图有问题。
我之前将 forceSimulation() 与一组对象一起使用,并且它有效。现在我更改了数据源,但它没有,即使控制台显示 no errors
我的数据是一个名为“lightWeight”的对象,结构如下:
我用它来附加圆圈:

// draw circles
var node = bubbleSvg.selectAll("circle")
   .data(d3.entries(lightWeight))
   .enter()
   .append("circle")
   .attr('r', function(d) { return scaleRadius(d.value.length)})
   .attr("fill", function(d) { return colorCircles(d.key)})
   .attr('transform', 'translate(' + [w/2, 150] + ')');

然后我创建模拟:

// simulate physics
  var simulation = d3.forceSimulation()
    .nodes(lightWeight)
    .force("charge", d3.forceCollide(function(d) { return d.r + 10; }))
    .force("x", d3.forceX())
    .force("y", d3.forceY())
  .on("tick", ticked); // updates the position of each circle (from function to DOM)

  // call to check the position of each circle
   function ticked(e) {
      node.attr("cx", function(d) { return d.x; })
          .attr("cy", function(d) { return d.y; });
  }

但圆圈仍然相互重叠,不会像以前那样变成气泡图。
如果这可能是一个愚蠢的问题,我深表歉意,我是 d3 的新手,对 forceSimulation() 的实际工作原理知之甚少。
例如,如果我用不同的数据多次调用它,生成的模拟会只影响指定的数据吗?
提前致谢!

【问题讨论】:

    标签: javascript json d3.js force-layout


    【解决方案1】:

    这里有几个问题:

    1. 您正在使用不同 数据集进行渲染和力模拟,即:.data(d3.entries(lightWeight)) 创建一个 对象数组,用于绑定到 DOM,而.nodes(lightWeight) 尝试在原始lightWeight 对象上运行力模拟(它需要一个数组,所以这不起作用)。

    尝试在任何代码开始之前执行var lightWeightList = d3.entries(lightWeight); 之类的操作,并将该数组用于绑定到 DOM 和作为力模拟的参数。当然,这应该清楚地表明,当涉及到更新您正在查看的节点时,您可能会遇到其他挑战 - 覆盖 lightWeightList 将破坏之前的任何节点位置(因为我们看不到更多你的代码,尤其是如何你第二次调用这个,我没有任何有用的想法)。

    1. 特别是如果您打算重新调用此代码,还有另一个问题:您链接.enter() 调用的方式意味着node 只会引用enter 选择——意思是也就是说,如果您再次调用此代码,则力模拟只会更新 ticked 内的 new 节点。

    使用 D3,我发现一个好习惯是将您的选择保存在单独的变量中,例如:

    var lightWeightList = d3.entries(lightWeight);
    
    // ...
    
    var nodes = bubbleSvg.selectAll('circle')
      .data(lightWeightList);
    var nodesEnter = nodes.enter()
      .append('circle');
    // If you're using D3 v4 and above, you'll need to merge the selections:
    nodes = nodes.merge(nodesEnter);
    nodes.select('circle')
         .attr('r', function(d) { return scaleRadius(d.value.length)})
         .attr('fill', function(d) { return colorCircles(d.key)})
         .attr('transform', 'translate(' + [w/2, 150] + ')');
    
    // ...
    
    var simulation = d3.forceSimulation()
      .nodes(lightWeightList)
      .force("charge", d3.forceCollide(function(d) { return d.r + 10; }))
      .force("x", d3.forceX())
      .force("y", d3.forceY())
      .on("tick", ticked);
    
    function ticked(e) {
      nodes.attr("cx", function(d) { return d.x; })
           .attr("cy", function(d) { return d.y; });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-13
      • 1970-01-01
      • 2014-11-20
      • 2020-03-25
      • 1970-01-01
      • 2013-05-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多