在angular

时间:2019-01-29 17:28:05

标签: angular typescript d3.js

我正在尝试根据以下代码在打字稿中编写堆积面积图:

http://jsfiddle.net/6LJjK/321/

我面临的问题是如何渲染堆栈。它们似乎不是从彼此的顶部“放置”,而是从y轴的0开始绘制,而且顺序也错误。我的猜测是与

有关

D3.stack()(<any>newDataset);的格式错误。

不输入任何内容我会遇到以下错误:

Argument of type '{ x: any; y: any; y0: number; }[][]' is not assignable to parameter of type '{ [key: string]: number; }[]'. Type '{ x: any; y: any; y0: number; }[]' is not assignable to type '{ [key: string]: number; }'. Index signature is missing in type '{ x: any; y: any; y0: number; }[]'.

我的代码:

ngAfterViewInit() {
    this.createChart();
  }

  getStackedData() {
    const dataset = [
      { year: 1, age1: 31, age2: 10, age3: 32, age4: 27 },
      { year: 2, age1: 32, age2: 12, age3: 30, age4: 26 },
      { year: 3, age1: 24, age2: 19, age3: 32, age4: 25 },
      { year: 4, age1: 26, age2: 18, age3: 31, age4: 25 },
      { year: 5, age1: 22, age2: 17, age3: 34, age4: 27 },
      { year: 6, age1: 24, age2: 17, age3: 33, age4: 26 },
      { year: 7, age1: 31, age2: 15, age3: 32, age4: 22 },
      { year: 8, age1: 30, age2: 15, age3: 35, age4: 20 },
      { year: 9, age1: 27, age2: 18, age3: 31, age4: 24 },
      { year: 10, age1: 25, age2: 15, age3: 35, age4: 25 },
      { year: 11, age1: 34, age2: 12, age3: 33, age4: 21 },
      { year: 12, age1: 31, age2: 14, age3: 32, age4: 23 },
      { year: 13, age1: 27, age2: 18, age3: 30, age4: 25 },
      { year: 14, age1: 25, age2: 20, age3: 35, age4: 20 }
    ];
    return dataset;
  }

  createChart() {
    const RecivedData = this.getStackedData();

    const svghHeight = 400;
    const svgWidth = 500;
    const marginTop = 10;
    const marginBottom = 20;
    const marginRight = 15;
    const marginLeft = 30;
    const chartHeight = 400 - marginTop - marginBottom;
    const Chartwidth = 500 - marginLeft - marginRight;


    const svgSelection = D3.select('#' + this.elementId).append('svg')
      .attr('width', svgWidth + marginLeft + marginRight)
      .attr('height', svghHeight + marginTop + marginBottom)
      .style('background-color', 'white')
      .attr('class', 'kpi-frame');


    const baseGroup = svgSelection
      .append('g')
      .attr('transform', 'translate(' + marginLeft + ',' + marginTop + ')');

    const yScale = D3.scaleLinear()
      .range([chartHeight, 0])
      .domain([0, 100]);

    const xScale = D3.scaleLinear().range([0, Chartwidth]);

    const yAxis = D3.axisLeft(yScale)
      .tickSize(2)
      .ticks(5)
      .tickFormat(function (d: any) { if (d === 100) { return d + '%'; } else { return d; } });


    const xAxis = D3.axisBottom(xScale).ticks(4);

    const newDataset = ['age1', 'age2', 'age3', 'age4'].map(function (n) {
      return RecivedData.map(function (d) {
        return { x: d.year, y: d[n], y0: 0};
      });
    });

      D3.stack()(<any>newDataset);


    xScale.domain(D3.extent(RecivedData, function (d) { return d.year; }));
    baseGroup.append('g')
      .attr('class', 'xaxis')
      .attr('transform', 'translate(0,' + chartHeight + ')')
      .call(xAxis);
    baseGroup.append('g')
      .attr('class', 'yaxis')
      .call(yAxis);


    const area = D3.area()
      .x(function (d: any) { return xScale(d.x); })
      .y0(function (d: any) { return yScale(d.y0); })
      .y1(function (d: any) { return yScale(d.y + d.y0); });


    const colors = ['#75d481', '#ff4848', '#ffac2e', '#7dbbf8'];

    const ageGroup = baseGroup.selectAll('.valgroup')
      .data(newDataset)
      .enter()
      .append('g')
      .attr('class', 'valgroup')
      .style('fill', function (d, i) {
        return colors[i];
      });

    ageGroup.append('path')
      .attr('d', function (d: any) {
        console.log(d);
        return area(d);
      });
  }
}

1 个答案:

答案 0 :(得分:0)

堆叠从v3更改为v4。我不确定旧版本的工作原理如何,但是在新版本中,您不需要const newDataset = ['age1', 'age2', 'age3', 'age4'].map( ... )部分,而是为堆栈生成器指定keys数组。

制作堆栈时,它将全部放入数组中,对于区域生成器,d包含一个2D数组-y0和y1值。对于x值,您可以访问d的data属性并从那里查找。

const dataset = [{
    year: 1,
    age1: 31,
    age2: 10,
    age3: 32,
    age4: 27
  },
  {
    year: 2,
    age1: 32,
    age2: 12,
    age3: 30,
    age4: 26
  },
  {
    year: 3,
    age1: 24,
    age2: 19,
    age3: 32,
    age4: 25
  },
  {
    year: 4,
    age1: 26,
    age2: 18,
    age3: 31,
    age4: 25
  },
  {
    year: 5,
    age1: 22,
    age2: 17,
    age3: 34,
    age4: 27
  },
  {
    year: 6,
    age1: 24,
    age2: 17,
    age3: 33,
    age4: 26
  },
  {
    year: 7,
    age1: 31,
    age2: 15,
    age3: 32,
    age4: 22
  },
  {
    year: 8,
    age1: 30,
    age2: 15,
    age3: 35,
    age4: 20
  },
  {
    year: 9,
    age1: 27,
    age2: 18,
    age3: 31,
    age4: 24
  },
  {
    year: 10,
    age1: 25,
    age2: 15,
    age3: 35,
    age4: 25
  },
  {
    year: 11,
    age1: 34,
    age2: 12,
    age3: 33,
    age4: 21
  },
  {
    year: 12,
    age1: 31,
    age2: 14,
    age3: 32,
    age4: 23
  },
  {
    year: 13,
    age1: 27,
    age2: 18,
    age3: 30,
    age4: 25
  },
  {
    year: 14,
    age1: 25,
    age2: 20,
    age3: 35,
    age4: 20
  }
];

const chartHeight = 200,
  chartWidth = 200;

const yScale = d3.scaleLinear()
  .range([chartHeight, 0])
  .domain([0, 100]);

const xScale = d3.scaleLinear()
  .domain([0, 14])
  .range([0, chartWidth]);

const colors = ['#75d481', '#ff4848', '#ffac2e', '#7dbbf8'];

var stackGen = d3.stack()
  .keys(["age1", "age2", "age3", "age4"]);

var stackedData = stackGen(dataset);

const area = d3.area()
  .x(function(d) {
    return xScale(d.data.year);
  })
  .y0(function(d) {
    return yScale(d[0]);
  })
  .y1(function(d) {
    return yScale(d[1]);
  });

var svg = d3.select('body')
  .append('svg')
  .attr('width', chartWidth)
  .attr('height', chartHeight);

const ageGroup = d3.select('svg').selectAll('.valgroup')
  .data(stackedData)
  .enter()
  .append('g')
  .attr('class', 'valgroup')
  .style('fill', function(d, i) {
    return colors[i];
  });

ageGroup.append('path')
  .attr('d', function(d) {
    return area(d);
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="chart1"></div>