Animation d3从条形图过渡到饼图并返回

Animation d3从条形图过渡到饼图并返回,animation,coffeescript,d3.js,Animation,Coffeescript,D3.js,所以我有一个想法,所有单轴数据都应该被允许以所有基本方式显示;至少从馅饼到酒吧。理想情况下,这将是一个生动的过渡,但这是困难来了 得到一个饼图和一个条形图是很容易的。以下是我到目前为止的情况: # fields width = 750 height = width/2 margin = 20 radius = (height-(margin*2))/2 # helpers pie = d3.layout.pie().value (d) -> d arc = d

所以我有一个想法,所有单轴数据都应该被允许以所有基本方式显示;至少从馅饼到酒吧。理想情况下,这将是一个生动的过渡,但这是困难来了

得到一个饼图和一个条形图是很容易的。以下是我到目前为止的情况:

# 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"  
显然,要让它工作,它必须是路径元素到路径元素,并且转换现在正在工作。问题是它看起来像垃圾。它一开始就看起来乱七八糟,直到它结束,变成像样的条形图

我一直在看这个: 这显示了一个酒吧以我喜欢的方式转变成了一个甜甜圈。查看源代码,这是通过自定义tween实现的。(查看源代码行518)

现在我在我头上。这是怎么回事?我怎样才能让这个过渡期开始工作?还有其他人处理过这个问题吗


更新

为了清楚起见,下面的插图更清楚地说明了我的过渡意图



悬赏清晰。我在这个问题上加了一个悬赏,因为我需要一个错误的解释。难以置信的是,他得到了赏金。然而,阿米特·阿维夫的方法是优越的,所以我认为他的回答是最正确的。我两个都做了+1e。D3在路径间插值方面做得很好,但是它在你原来的前后路径上遇到了问题,所以我想也许我们可以找到更好的路径,让D3的工作更容易。我的

第一件事是查看svg arc path元素。基本上是这样的:

A rx,ry a f1,f2 x,y 
您可以阅读详细信息。这将从您所在的位置(上一个最终坐标)到坐标x,y绘制一条圆弧。但需要重点关注的是,前两个数字是隐含椭圆的半径,最后一个在端点坐标之前的部分,我已经标记了f1,f2,是标志,因此不能插值

因此,代码转换过程中的主要奇怪之处在于,您试图在

A rx,ry,0,1

A 0,0,0

如果在一种情况下将端点路径设置为A0,0,1,您将立即看到更平滑的过渡

为了使各部分更好地结合在一起,我设置了饼图内径的动画,使各部分看起来更像条,但呈曲线状,然后让D3计算出曲线到条的过渡,但不切换圆弧标志。然后你想让酒吧有平头。如果增加隐含椭圆半径,路径将具有更平坦的圆弧!所以我只用了100100。我的最后一次转换为条形图的路径如下所示:

"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计算的转换回甜甜圈图效果良好。然后,我简单地设置了内半径的动画

以下是我的看法:

我的方法是使用三次贝塞尔曲线来近似圆弧和条形,控制点的数量完全相同。代码有点复杂,需要做一些工作。但结果相当顺利

这是一个摘录(因此需要…)


我只能看到HTML中的第660行…我应该看另一个文件吗?你是对的。它的518,除了任何技术问题,你会如何动画从一个楔子到一个酒吧?甜甜圈到酒吧很容易,因为甜甜圈的“楔子”实际上只是弯曲的酒吧,所以你所需要做的就是把它们拉直。楔块自然不适合这种变换。如果你添加一个中间步骤饼->甜甜圈->条,这有助于你达到你想要的效果吗?@ColinYoung从一个楔子到一个条不是不可能的,因为在d3中,楔子只是一个洞大小为零的甜甜圈。我需要的是帮助理解如何从d3框架和数学角度实现转换。一个粗略但相当简单的方法:你的解决方案非常有效。但是,例如,当我用一个很大的差异[2,3,24]来更新数组的值时,d3在转换过程中抛出了一个无效的路径-jsfiddle here:。你知道为什么d3不能顺利过渡吗?谢谢!从控制台输出来看,我认为科学符号让SVG感到困惑。构建路径字符串时,请确保设置数字格式,使其成为常规浮点数。您得到的数字非常小,可能会被0替换。
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;
}