D3饼图在进入并更新angular应用程序时设置动画

D3饼图在进入并更新angular应用程序时设置动画,angular,d3.js,d3pie.js,Angular,D3.js,D3pie.js,我正在我的应用程序中使用D3派来可视化一些数据。我能够正确显示数据。我只想让图表在进入时设置动画。似乎当我改变数据时,它的动画效果很好。我在这里模拟了代码 主要问题是,当我在“回车”中添加arcTween时,它会抛出一个错误 const data=pie().sort(null).value((d:any)=>d.value)(rawData); const{height,radius}=this.dimensions; const slices=this.svg.select(`.slice

我正在我的应用程序中使用D3派来可视化一些数据。我能够正确显示数据。我只想让图表在进入时设置动画。似乎当我改变数据时,它的动画效果很好。我在这里模拟了代码

主要问题是,当我在“回车”中添加arcTween时,它会抛出一个错误

const data=pie().sort(null).value((d:any)=>d.value)(rawData);
const{height,radius}=this.dimensions;
const slices=this.svg.select(`.slices${this.id}`);
//内部切片输入/更新/删除(对于甜甜圈)
const innerSliceUpdate=slices.selectAll(`.innerSlice${this.id}`).data(data);
const innerSliceCenter=innerSliceUpdate.enter().append('path').attr('class','innerSlice${this.id}`);
innerSliceUpdate.exit().remove();
内部切片输入
.style('fill',(d:any)=>hsl(d.data.color)。颜色更深(0.7)。toString()
.style(“过渡”,切片动画)
.attr('d',d=>this.pieInner(d,半径.x+0.5,半径.y+0.5,半径.z,高度))
.each(d=>{this.interpolators[d.data.label]=d;});
内部切片更新
.transition().duration(动画持续时间*1e3)
.attrween('d',d=>(t,i=this.interpolatorFn(d)(t))=>this.pieInner(i,半径x+0.5,半径y+0.5,半径z,高度));
//顶部切片输入/更新/删除(面向x/y轴)
const topliceupdate=slices.selectAll(`.toplice${this.id}`).data(data);
const toplicecenter=topliceupdate.enter().append('path').attr('class','toplice${this.id}`);
topliceupdate.exit().remove();
上立轴
.style('fill',d=>d.data.color)
.style('stroke',d=>d.data.color)
.style(“过渡”,切片动画)
.attr('d',d=>this.pieTop(d,radius.x,radius.y,radius.z))
.each(d=>{this.interpolators[d.data.label]=d;});
//*******正在尝试在此处添加一个弧间*******
上片更新
.transition().duration(动画持续时间*1e3)
.attrween('d',d=>(t,i=this.interpolatorFn(d)(t))=>this.pieTop(i,radius.x,radius.y,radius.z));
D3新手,欢迎提供任何帮助


注意:寻找一个解决方案来了解和理解我做错了什么

实现动画的一种方法是使用一些与当前初始化值不同的值来初始化图表切片,然后使用一个生命周期挂钩,如ngAfterViewInit()来设置实际的初始值。基于现有代码,类似于:

export class AppComponent  {
  name = 'Angular ' + VERSION.major;
  data = [
    { key: 'inprogress', color: 'yellow', label: 'In Progress', value: 0 },
    { key: 'completed', color: 'green', label: 'Completed', value: 0 },
    { key: 'delayed', color: 'red', label: 'Delayed', value: 0 },
  ];  
   ngAfterViewInit(){
     this.data = [
    { key: 'inprogress', color: 'yellow', label: 'In Progress', value: 3 },
    { key: 'completed', color: 'green', label: 'Completed', value: 18 },
    { key: 'delayed', color: 'red', label: 'Delayed', value: 5 },
   ];
  }

  constructor(){
    setTimeout(() => {
      this.data = [
        { key: 'inprogress', color: 'yellow', label: 'In Progress', value: 5 },
        { key: 'completed', color: 'green', label: 'Completed', value: 5 },
        { key: 'delayed', color: 'red', label: 'Delayed', value: 15 },
      ]
    }, 2000)
  }
}

下面是另一个
hacky
解决方案,尽管更容易实现。它使用了@amishra实现的相同思想

在您的piechart.component.ts中更改
ngAfterViewInit()

ngAfterViewInit():void{
this.id=`{Math.floor(Math.random()*5e10)}`;
this.init();
如果(this.data&&this.data.length>=0){
this.draw(this.data.map(item=>({…item,value:1}));//这段代码

topSliceEnter
   ....
   .attr("d", d => this.pieTop(d, radius.x, radius.y, radius.z))
明确地说,新添加的项目将以“完成”状态渲染,这没有多大意义,如果您想要设置某个项目的动画,那么您需要从要设置动画的起点开始

假设您想从
{startAngle:0,endAngle:0.1}
制作图表动画。希望您没有期望我重构您的所有代码,因此我修复了
顶层片
部分:


另外,您的代码中存在一些错误,无法正确处理更新,例如颜色更改,这是一个黑客行为。我正在寻找解决方案。感谢您的努力,但确实在寻找一个解决方案来了解和理解我的错误。感谢您的想法是合并。这非常完美。是的,我可以从这里开始。非常感谢
topSliceEnter
   ....
   .attr("d", d => this.pieTop(d, radius.x, radius.y, radius.z))
topSliceEnter 
      ......
      .attr("d", d => this.pieTop({startAngle: 0, endAngle: 0.1}, radius.x, radius.y, radius.z))
       .each(d => {
        this.interpolators[d.data.label] = {...d, startAngle: 0, endAngle: 0.1};
         // I would refactor this. the interpolation logic looks strange, but still this will make your example animate fine.
      });

topSliceUpdate.merge(topSliceEnter) // merge will make next transition to be applied on both entering and updating elements
  .transition()
...