如何处理d3中Beeswarm图中的碰撞? [英] How to handle collisions in Beeswarm plot in d3?
问题描述
我一直在玩这个例子这里一会儿。我想做的是突出显示单个节点/圆圈(通过使其更大的边框;后来我想添加文本或其中的字母)。
I've been playing around with this example here for a little while. What I'm trying to do is highlight a single node/circle in the plot (by making it larger with a border; later I want to add text or a letter inside it too).
目前,我已将不丹
的圈子放大,如下所示:
Currently, I've made the circle for Bhutan
larger in the plot like the following:
.attr("r",
function(d){return ( d.countryName === "Bhutan" ? r + 4 : r);})
.attr("stroke", function(d){if (d.countryName==="Bhutan"){return "black"}})
但是,它与其他圈子重叠。什么是避免这些冲突/重叠的最佳方法?提前致谢。
However, it overlaps with the other circles. What would be the best approach to avoid these collisions/overlaps? Thanks in advance.
链接到Plunkr - https:/ /plnkr.co/edit/rG6X07Kzkg9LeVVuL0PH?p=preview
Link to Plunkr - https://plnkr.co/edit/rG6X07Kzkg9LeVVuL0PH?p=preview
我尝试以下操作来添加字母bhutan圆圈
I tried the following to add a letter inside the bhutan circle
//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
Updated Plunkr - https://plnkr.co/edit/Bza5AMxqUr2HW9CYdpC6?p=preview
推荐答案
这是一个稍微不同的问题,在这个问题在这里:如何更改D3.js中的蜂巢图中的点的大小
This is a slightly different problem than in this question here: How to change the size of dots in beeswarm plots in D3.js
你可以想到几个选项:
- 设置
forceCollide
成为你的最大可能半径* 1.33
,例如(r + 4)* 1.33
。 - 将radius属性添加到数组中的每个条目,并使碰撞工作基于它,它
- Set the
forceCollide
to be yourlargest possible radius * 1.33
, e.g.(r + 4) * 1.33
. This will prevent overlapping, but spread things out a lot and doesn't look that great. - Add the radius property to each entry in your array and make the collide work based off that, which will look a bit better but not perform as awesomely for large sets.
下面是一个例子:
...
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; })
....
使用在
d3.csv
中为 r
的每个成员添加一个属性的code>请检查国家/地区名称以确定哪个国家/地区获得的值较大。
Use the row
function in d3.csv
to add a property to each member of the array called r
, and check the country name to determine which one gets the larger value. Then use that value wherever you need to mess with the radius.
我猜想在半径受到影响的地方可以检查国家名称(例如 .force(collide,d3.forceCollide(function(d){return d.countryName ===Bhutan?(r + 4)* 1.33:r * 1.33;})
,等等)。这对我来说有点干净,但它可能通过从数据条目本身抽象出半径来更清洁...
I guess it would've been possible to check the country name everywhere the radius was impacted (e.g. .force("collide", d3.forceCollide(function(d) { return d.countryName === "Bhutan" ? (r + 4) * 1.33 : r * 1.33; })
, etc.). This feels a bit cleaner to me, but it might be cleaner still by abstracting out the radius from the data entries themselves...
Forked您的plunk: https://plnkr.co/edit/Tet1DVvHtC7mHz91eAYW?p=preview
Forked your plunk here: https://plnkr.co/edit/Tet1DVvHtC7mHz91eAYW?p=preview
这篇关于如何处理d3中Beeswarm图中的碰撞?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!