所以我认为应该允许所有单轴数据以所有基本方式显示;至少从馅饼到酒吧。理想情况下,这将是一个动画过渡,但那就是难度。
获取饼图很容易,就像获取条形图一样。以下是我到目前为止的情况:
# fields
width = 750
height = width/2
margin = 20
radius = (height-(margin*2))/2
# helpers
pie = d3.layout.pie().value (d) -> d
arc = d3.svg.arc()
.outerRadius(radius)
.innerRadius(radius/4)
x = d3.scale.linear().domain([0, 100]).range [0, width]
$http.get('/Classification_Top_10_by_Count.json').success (data) ->
percents = (parseFloat item.Percent for item in data).sort d3.ascending
svg = d3.select('#svgStage').append('svg')
.attr('width', width+(margin*2))
.attr('height', height+(margin*2))
svg.data([percents])
g = svg.append('g')
.attr('transform', "translate(#{radius},#{radius})")
paths = g.selectAll 'path'
paths.data(pie).enter().append('path')
.attr('d', arc)
toBars = ->
g.selectAll('path').transition().duration(2000)
.attr 'd', (d, index) ->
# this is over complex because I was playing with it.
cord =
tl : [0, index*20]
tr : [d.value*20, index*20]
br : [d.value*20, index*20-20]
bl : [0, index*20-20]
oCord = [
cord.tl
cord.tr
cord.br
cord.bl
]
"M #{oCord[0][0]}, #{oCord[0][2]}
A 0, 0 0 0, 0 #{oCord[1][0]}, #{oCord[1][3]}
L #{oCord[2][0]}, #{oCord[2][4]}
A 0, 0 0 0, 0 #{oCord[3][0]}, #{oCord[3][5]}
Z"
显然,为了实现这一点,它必须是路径元素的路径元素,现在转换正在进行。问题是它看起来像垃圾。它开始的那一刻看起来很乱,直到它结束并成为不错的条形图。
我一直在看这个:http://d3-example.herokuapp.com/examples/showreel/showreel.html 这表明酒吧以我想要的方式过渡到甜甜圈。查看源代码,这是通过自定义补间完成的。 (查看源代码行518)
现在我已经过了头。这里发生了什么?如何让这种转变发挥作用?有谁在那里处理这个问题?
更新
为了清楚起见,在下面的插图中,我的过渡意图更加清晰。
赏金清晰度。我为这个问题添加了一笔赏金,因为我需要解释出错的地方。 Superboggly做到了这一点,所以他得到了赏金。然而Amit Aviv的方法更优越,所以我接受他的答案是最正确的。我也同时加了两个。
答案 0 :(得分:9)
首先要看svg弧路径元素。它基本上是这样的:
A rx,ry a f1,f2 x,y
您可以阅读详细信息here。这将从您(前一个最终坐标)到坐标x,y的任何地方绘制一条圆弧。但要关注的是前两个数字是隐含椭圆的半径,最后一个部分是在结束坐标之前,我标记为 f1,f2 ,是标志,因此不能插入
因此,从代码转换的主要奇怪之处在于您尝试在
之间进行插值rx,ry,0 0, 1
A 0,0 0 0, 0
如果在一种情况下将结束路径设置为A0,0 0 0,1,您将立即看到更平滑的过渡。
为了使这些部分更好地融合在一起,我对饼的内部半径进行了动画处理,使得这些部分看起来更像是条形但是弯曲,然后我让D3计算出曲线到条形的过渡但没有切换弧形标记。然后你希望条形有扁平的末端。如果增加隐含的椭圆半径,则路径将具有更平坦的弧度!所以我只使用了100,100。我对酒吧的最终转换路径如下:
"M " + oCord[0][0] + "," + oCord[0][1] +
"A100,100 0 0,1 " + oCord[1][0] + "," + oCord[1][1] +
"L " + oCord[2][0] + "," + oCord[2][1] +
"A100,100 0 0,0 " + oCord[3][0] + "," + oCord[3][1] +
"Z";
然后实际上,正确地,平整端点,我有第二个转换(它们串行运行),以使路径的弧段为零。我怀疑有一种更好的方法可以使用D3转换进行这种清理,但是持续时间为0的转换也可以。
为了使反面工作顺利,我将路径设置为从上方的扁平弧曲线。具有大半径和正确的标记意味着D3计算的转换回到圆环图表运行良好。然后我简单地将内半径动画回来。
答案 1 :(得分:9)
以下是我的观点:http://jsfiddle.net/amitaviv99/x6RWs/42/
我的方法是近似弧线和弧线。使用三次贝塞尔曲线的条形图,具有完全相同的控制点数。代码有点复杂,需要一些工作。但结果非常顺利。
这是一段摘录(SO要求......)
var bezierArc = function(radiusIn, radiusOut, startAngle, endAngle){
var arcIn = makeCompArc(radiusIn, startAngle, endAngle);
var arcIOut = makeCompArc(radiusOut, startAngle, endAngle);
var lines = makeBezierDoubleLine(radiusIn, radiusOut, startAngle, endAngle);
var path = [arcIn, lines[0], arcOut, lines[1]].join(' ');
return path;
}