D3.js 在树、簇、径向树和径向簇布局之间平滑过渡

D3.js 在树、簇、径向树和径向簇布局之间平滑过渡,d3.js,hierarchy,hierarchical-data,dendrogram,D3.js,Hierarchy,Hierarchical Data,Dendrogram,对于一个项目,我需要以交互方式更改可视化的分层数据布局,而不改变任何底层数据。能够在它们之间切换的布局应该是树、簇、放射状树和放射状簇。过渡最好是动画 我认为使用D3,这将是一项相对容易的任务。我开始了,但是我在平移和旋转、数据绑定和类似的过程中迷失了方向,所以我请求您的帮助。另外,我可能在做一些不符合D3精神的事情,这是不好的,因为我正在寻找一个干净的解决方案 我制作了一个,但这只是一个起点,添加了单选按钮,方便的小数据集,以及初始集群布局-只是为了帮助任何想了解这一点的人。提前谢谢 更新:

对于一个项目,我需要以交互方式更改可视化的分层数据布局,而不改变任何底层数据。能够在它们之间切换的布局应该是树、簇、放射状树和放射状簇。过渡最好是动画

我认为使用
D3
,这将是一项相对容易的任务。我开始了,但是我在平移和旋转、数据绑定和类似的过程中迷失了方向,所以我请求您的帮助。另外,我可能在做一些不符合D3精神的事情,这是不好的,因为我正在寻找一个干净的解决方案

我制作了一个,但这只是一个起点,添加了单选按钮,方便的小数据集,以及初始集群布局-只是为了帮助任何想了解这一点的人。提前谢谢

更新:

我只想关注链接,所以暂时禁用了其他元素。基于@AmeliaBR方法,获得以下动画:

这是

更新2:

现在是圆圈:(请原谅我选择的颜色)

{doom duba doom}


这就是。

我不明白,只要所有布局都具有相同的链接路径、圆节点和文本标签的总体结构,为什么会有那么难

只需确保所有对象(包括链接路径)都有一个良好的数据键,该键独立于布局函数创建的数据属性。然后,对于每个转换,使用相应布局函数的结果更新数据并绘制该布局

我在这里实现了到径向树的转换:

关键代码:

//Radial Tree layout//
var diameter = 500;
var radialTree = d3.layout.tree()
    .size([360, diameter / 2 ])
    .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });
var radialDiagonal = d3.svg.diagonal.radial()
    .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });
function transitionToRadialTree() {
  var nodes = radialTree.nodes(root), //recalculate layout
      links = radialTree.links(nodes);

    svg.transition().duration(1500)
       .attr("transform", "translate(" + (diameter/2)
                 + "," + (diameter/2) + ")");
             //set appropriate translation (origin in middle of svg)

    link.data(links, function(d){
              return d.source.name + d.target.name;})
      .transition().duration(1500)
      .attr("d", radialDiagonal); //get the new radial path

  node.data(nodes, function(d){
              return d.name ;})
      .transition().duration(1500)
      .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; }) 

  node.select("circle")
      .transition().duration(1500)
      .attr("r", 4.5);

  node.select("text")
      .transition().duration(1500)
      .attr("dy", ".31em")
      .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
      .attr("transform", function(d) { return d.x < 180 ? "translate(8)" : "rotate(180)translate(-8)"; });
};
//放射状树布局//
var直径=500;
var radialTree=d3.layout.tree()
.尺寸([360,直径/2])
.separation(函数(a,b){return(a.parent==b.parent?1:2)/a.depth;});
var radialDiagonal=d3.svg.diagonal.radial()
.投影(函数(d){return[d.y,d.x/180*Math.PI];});
函数TransitionRadialTree(){
var nodes=radialTree.nodes(根),//重新计算布局
链接=径向树。链接(节点);
svg.transition().持续时间(1500)
.attr(“变换”、“平移”(+(直径/2))
+“,”+(直径/2)+“)”;
//设置适当的转换(svg中间的原点)
链接。数据(链接,功能(d){
返回d.source.name+d.target.name;})
.transition().持续时间(1500)
.attr(“d”,径向对角线);//获取新的径向路径
节点。数据(节点,函数(d){
返回d.name;})
.transition().持续时间(1500)
.attr(“转换”,函数(d){return”旋转(“+(d.x-90)+”)平移(“+d.y+”);})
节点。选择(“圆”)
.transition().持续时间(1500)
.attr(“r”,4.5);
节点。选择(“文本”)
.transition().持续时间(1500)
.attr(“dy”,“.31em”)
.attr(“文本锚定”,函数(d){返回d.x<180?“开始”:“结束”})
.attr(“transform”,函数(d){返回d.x<180?“translate(8)”:“rotate(180)translate(-8)”;});
};
布局代码全部来自,我刚刚将其更改为更新,而不是初始化

还要注意,我已经将
root
的变量声明移到了数据读取方法之外,因此可以通过转换函数重新访问它

布局仍然需要一些改进,但你已经明白了


现在,如果您希望其中一个转换是一个分区、树形图或其他不使用节点链接结构的布局,它们会变得更复杂…

我没有足够的声誉发表评论…因此,我只是作为一个伪答案给出这一微小贡献。在看了这篇文章之后,基于@lividd对转换结果是多么简单的完美评论,我只是在本文中的转换中添加了树垂直选项

增加的内容很简单:

var diagonalVertical = d3.svg.diagonal()
    .projection(function (d) { 
        return [d.x, d.y]; 
    });

无论如何,我已经将这种高度指导性的互动添加到书签中。

我所知道的唯一接近这一点的是。我怀疑你是否能在这里得到一个好的答复,因为这需要做很多工作才能实现。我从来没有想过这会有那么高的要求。可能不会,尽管我怀疑使转换顺利进行可能会有点麻烦,特别是当你在欧几里德坐标和极坐标之间转换时。因此,一个简单的转换看起来可能不是特别好。谢谢你的链接!这正是我想要的。我可能会对它进行一些重构,如果重构了,我会发布一个新的JSFIDLE!;-)令人大开眼界的回答。在技术意义上,链接转换解决方案的简单性最让我惊讶。此外,我将过渡持续时间增加到15秒,整个过程看起来非常精彩。我将尝试根据您的方法编写一个示例,并将在几天后返回,结果是……太棒了!这里还有一个()和.delay(函数(d,i){return 100*i+500*d.source.depth;}),只是为了好玩。技术与艺术相遇!这些看起来都非常棒——感谢您将动画嵌入到主贴子@livided中。真正展示了布局功能的潜力以及它们下面的通用D3结构的好处。