创建具有不同堆叠级别的堆叠条形图

时间:2018-09-18 16:00:06

标签: d3.js vue.js stacked-chart

此代码在VUEJ的框架内。

我正在创建一个堆积的条形图,但无法使用D3堆积功能。 所以我尝试以其他方式实现矩形的y位置和高度。

这是我拥有的数据:

tasks: [
  {
    name:t1,
    taskTotal:1000
    taskStages: [
       { 
        stageTotal: 200 
       },
       { 
        stageTotal: 400 
       },{ 
        stageTotal: 400 
       }
    ]
    
  },
  {
    name:t2,
    taskTotal:500
    stages:[
          { 
            stageTotal: 200 
          },
          {
            stageTotal: 300
          }
    ],
  }
]

我曾尝试为每个任务量身定做秤,但没有成功。

每个Bar的x pos都很好,我的问题是矩形和高度的y pos。

这是我目前拥有的代码:

getScaleForTask(task){
  return d3.scaleLinear()
    .range([0,this.svgHeight - 20])
    .domain([0,task.taskTotal])
},


TaskCumulativeTotal(taskStages){
  const arrOFCumulativeSums = [0]
   taskStages.reduce((sumOfStages,currStage) => {
       arrOFCumulativeSums.push(currStage.stageTotal + sumOfStages)
       return currStage.stageTotal + sumOfStages;
     },0);
  return arrOFCumulativeSums
},
    
chartBuilder(){
  let currCumulativeSum;
  let yScaleForTask;

  
  const taskG = svg
          .selectAll('g')
          .data(this.tasks)
          .enter()
          .append('g')
          .attr(
            'transform',
            (d, i) => `translate(${cunmulativeGroupXPos[i]},0)`,
          );
          
  // from here i'm stuck
  const stageG = taskG
          .selectAll('g')
          .data(d =>{ 
              yScaleForTask = this.getScaleForTask(d);
              currCumulativeSum = this.TaskCumulativeTotal(d.taskStages); 
              return d.taskStages; 
            })
          .enter()
          .append('g')
          .attr('transform', d => xScale(d.taskName)); // this determins the x pos

        stageG
          .append('rect')
          .attr('width', 30)
          .attr('y', (d,i) => yScaleForTask(currCumulativeSum[i]))
          .attr('height', d => yScaleForTask(d.stageTotal))
          .attr('fill', (d, i) => (i % 2 === 0 ? '#66ccff' : '#99ff66'))
          .attr('stroke', 'grey');
 }

这是目前的样子 enter image description here

我一直在努力使每个任务阶段相互叠加, 我确实读过D3 Stacked bar chart with different stack level

https://bl.ocks.org/DimsumPanda/689368252f55179e12185e13c5ed1fee

1 个答案:

答案 0 :(得分:0)

找到一种使其工作的方法:发布代码以供将来参考。

我解决此问题的方法是遍历任务,并为每个任务添加一个组,并在每个组内部添加条形图。

这样,我就不会失去y位置所需的累计和。

    chartBuilder() {
    
      const longestTask = this.getLongestTask();
      const taskNames = this.tasks.map(t => t.taskName);
      const xScale = d3.scaleBand()
        .domain(taskNames)
        .rangeRound([0, this.svgWidth]);
      const svg = d3.select('#stacked-svg-tasks');
      const yScaleForTask = this.getScaleForTask(this.svgHeight - 20, longestTask);

      const barWidthScale = Math.round(this.svgWidth / this.tasks.length) - this.GbGS;
      // adding data to show as bar chart
      this.tasks.forEach((task, taskIndex) => {
        const currCumulativeSum = this.CumulativeTimeOfStages(task.taskStages);
        const data = [task];

        const currTask = svg
          .selectAll(`bar${taskIndex}`)
          .data(data)
          .enter()
          .append('g')
          .attr('class', `bar${taskIndex}`)
          .attr(
            'transform',
            `translate(${xScale(task.taskName)},0)`,
          )
          .selectAll('rect')
          .data(d => d.taskStages)
          .enter()
          .append('rect')
          .attr('y', (d, i) => this.svgHeight - yScaleForTask(currCumulativeSum[i]))
          .attr('width', barWidthScale)
          .attr('height', d => yScaleForTask(d.totalTime))
          .attr('fill', (d, i) => (i % 2 === 0 ? '#66ccff' : '#99ff66'));
      });