我正在玩一点 D3.js 并且我得到了大部分工作。但我想将我的 svg 形状放在一个圆圈中。所以我会用颜色和文字来展示数据的差异。我知道如何画圆圈和饼图,但我想基本上有一个相同大小的圆圈。并且不要让它们重叠,顺序无关紧要。我不知道从哪里开始,找出每个圆圈的 x 和 y。
2 回答
如果我理解正确,这是一个相当标准的数学问题:
只需以适当的步长循环某个角度sin()
变量,然后使用andcos()
来计算您的 x 和 y 值。
例如:
假设您要放置 3 个对象。一个圆圈有 360 度。所以每个对象都与下一个对象相差 120 度。如果您的对象大小为 20x20 像素,请将它们放置在以下位置:
x1 = sin( 0 * pi()/180) * r + xc - 10; y1 = cos( 0 * pi()/180) * r + yc - 10
x2 = sin(120 * pi()/180) * r + xc - 10; y2 = cos(120 * pi()/180) * r + yc - 10
x3 = sin(240 * pi()/180) * r + xc - 10; y3 = cos(240 * pi()/180) * r + yc - 10
这里,r
是圆的半径,是(xc, yc)
圆的中心点的坐标。确保对象的-10's
中心(而不是左上角)在圆上。将* pi()/180
度数转换为弧度,这是大多数实现sin()
和cos()
需要的单位。
注意:这会将形状均匀分布在圆圈周围。为确保它们不重叠,您必须选择r
足够大的。如果对象具有简单且相同的边界,只需布置其中的 10 个并计算出您需要的半径,然后,如果您需要放置 20 个,则将半径设为两倍,30 设为三倍,依此类推。如果对象是不规则形状的,并且您想将它们以最佳顺序围绕圆圈放置以找到可能的最小圆圈,那么这个问题将变得非常混乱。也许有一个库可以解决这个问题,但我的脑海中没有一个库,而且由于我没有使用过 D3.js,我不确定它是否也会为您提供此功能。
这是另一种方法,用于任意大小的形状,使用 D3 的tree
布局:http: //jsfiddle.net/nrabinowitz/5CfGG/
tree
布局(文档,示例)将根据给定的半径和返回任意两个项目中心之间距离的函数为您计算出每个项目的 x,y 位置。在这个例子中,我使用了不同大小的圆,所以它们之间的间隔是它们半径的函数:
var tree = d3.layout.tree()
.size([360, radius])
.separation(function(a, b) {
return radiusScale(a.size) + radiusScale(b.size);
});
使用 D3tree
布局解决了第一个问题,将项目布置成圆形。正如@Markus 所指出的,第二个问题是如何计算圆的正确半径。为了方便起见,我在这里采取了一种稍微粗略的方法:我将圆的周长估计为各种项目的直径之和,中间有给定的填充,然后从周长计算半径:
var roughCircumference = d3.sum(data.map(radiusScale)) * 2 +
padding * (data.length - 1),
radius = roughCircumference / (Math.PI * 2);
这里的圆周并不精确,圆圈中的项目越少,这个圆周就越不准确,但对于这个目的来说它已经足够接近了。