【问题标题】:D3 adding force to single nodeD3 对单个节点加力
【发布时间】:2017-02-25 15:01:04
【问题描述】:

我使用 D3 的力布局制作了一个分组气泡图,以创建一个朝向中间的力,如下所示:

  var forceStrength = 0.03;
  var center = { x: widthBubbles / 2, y: heightBubbles / 2 };

  var simulation = d3.forceSimulation()
     .velocityDecay(0.2)
     .force('x', d3.forceX().strength(forceStrength).x(center.x))
     .force('y', d3.forceY().strength(forceStrength).y(center.y))
     .force('charge', d3.forceManyBody().strength(charge))
     .on('tick', ticked);

  function charge(d) {
    return -forceStrength * Math.pow(d.r, 2.0);
  }

  function ticked() {
    bubbles
      .attr('cx', function (d) { return d.x; })
      .attr('cy', function (d) { return d.y; });
  }

我的图表看起来类似于:Gates Foundation Educational Spending

我希望能够在单击单个节点时对其施加力,以便单击的节点将移动到另一个区域。在 D3 的文档中有一个叫做“定位力”的东西,根据文档,它旨在用于多个节点:

虽然这些力可用于定位单个节点,但它们主要用于适用于所有(或大多数)节点的全局力。

所以我的问题是是否有办法对 D3 中的单节点施加力。

【问题讨论】:

标签: javascript d3.js force-layout


【解决方案1】:

我通过创建一个函数解决了这个问题,每次点击气泡时都会调用该函数:

  //Function for moving bubbles when selected
  function moveSelectedBubbles() {
    simulation.force('x', d3.forceX().strength(forceStrength).x(function(d){
      //Check if bubble is selected
      return (selectedCountries.indexOf(d.data.country) >= 0) ? selectedCenter.x : center.x;
    }));

  simulation.alpha(1).restart();

  }

但是这个函数会在每次选择气泡时设置每个节点的力。也许有一种更有效的方式来处理这个案子。

【讨论】:

  • 从您的解决方案看来,您的力实际上作用于所有节点,因为如果未选择它,您将其设置为 center.x。如果不是这种情况,并且您只想隔离一个节点/一组节点,那么有一个很酷的 mbostock 最近块:bl.ocks.org/mbostock/b1f0ee970299756bc12d60aedf53c13b,我发现它很有用。另外,我认为您应该能够将您的 .x(function(d)... 代码移动到 forceX(here) 函数内以简化事情(我不认为您应该在每次点击处理程序时都设置此力) .
  • 还有一件事:您还可以在 d 对象本身上存储一个临时标志,例如d.isSelected 并对其进行过滤,而不是每次都重新计算 indexOf。 (显然,这还需要您处理何时将此标志设置为 false。)
  • 感谢您的评论。我会检查一下。
猜你喜欢
  • 2012-09-11
  • 1970-01-01
  • 1970-01-01
  • 2019-04-23
  • 1970-01-01
  • 2014-12-05
  • 2014-10-03
  • 2014-06-23
  • 2020-08-29
相关资源
最近更新 更多