如何处理d3中的Beeswarm情节中的碰撞?

时间:2017-03-06 19:17:09

标签: javascript d3.js

我一直在玩这个例子here一段时间。我想要做的是在图中突出显示单个节点/圆圈(通过使边框更大;稍后我想在其中添加文字或字母)。

目前,我已经在情节中为Bhutan做了更大的圈子,如下所示:

.attr("r", 
    function(d){return ( d.countryName === "Bhutan" ? r + 4 : r);})
.attr("stroke", function(d){if (d.countryName==="Bhutan"){return "black"}})

但是,它与其他圈子重叠。什么是避免这些碰撞/重叠的最佳方法?提前致谢。

链接到Plunkr - https://plnkr.co/edit/rG6X07Kzkg9LeVVuL0PH?p=preview

我尝试了以下内容在不丹圈内添加一个字母

    //find bhutan circle and add a "B" to it
    countriesCircles
    .data(data)
  .enter().append("text")
  .filter(function(d) { return d.countryName === "Bhutan"; })
    .text("B");

更新了Plunkr - https://plnkr.co/edit/Bza5AMxqUr2HW9CYdpC6?p=preview

1 个答案:

答案 0 :(得分:3)

这个问题与此问题略有不同:How to change the size of dots in beeswarm plots in D3.js

您可以考虑以下几个选项:

  • forceCollide设为您的largest possible radius * 1.33,例如(r + 4) * 1.33。这样可以防止重叠,但会将事情分散开来并且看起来不那么好。
  • 将radius属性添加到数组中的每个条目,并使碰撞工作基于此,这看起来会更好但对大型集合执行效果不佳。

以下是如何执行此操作的示例:

...
d3.csv("co2bee.csv", function(d) {
    if (d.countryName === "Bhutan") {
      d.r = r + 4;
    } else {
      d.r = r;
    }
    return d;
}, function(error, data) {
    if (error) throw error;
    var dataSet = data;
...
var simulation = d3.forceSimulation(dataSet)
  ...
  .force("collide", d3.forceCollide(function(d) { return d.r * 1.33; }))
  ...

countriesCircles.enter()
    .append("circle")
    .attr("class", "countries")
    .attr("cx", 0)
    .attr("cy", (h / 2)-padding[2]/2)
    .attr("r",  function(d){ return d.r; })
....

使用row中的d3.csv函数向名为r的数组的每个成员添加属性,并检查国家/地区名称以确定哪个获取更大的值。然后在任何需要使用半径的地方使用该值。

我想在半径受影响的地方(例如.force("collide", d3.forceCollide(function(d) { return d.countryName === "Bhutan" ? (r + 4) * 1.33 : r * 1.33; })等)可以查看国家/地区名称。这对我来说感觉有点干净,但是通过从数据条目本身抽象出半径,它可能更清晰......

在这里分叉你的插件:https://plnkr.co/edit/Tet1DVvHtC7mHz91eAYW?p=preview