创建具有不同堆叠级别的堆叠条形图
Create a stacked bar chart with different stack level
此代码位于 VUEJs 框架内。
我正在努力创建堆叠条形图,但无法使用 D3 堆叠功能。
所以我尝试以不同的方式实现矩形的 y 位置和高度。
这是我的数据:
tasks: [
{
name:t1,
taskTotal:1000
taskStages: [
{
stageTotal: 200
},
{
stageTotal: 400
},{
stageTotal: 400
}
]
},
{
name:t2,
taskTotal:500
stages:[
{
stageTotal: 200
},
{
stageTotal: 300
}
],
}
]
我曾尝试为每个任务制定特定的比例,但没有成功。
每个条形的 x 位置都很好,我的问题是矩形的 y 位置和高度。
这是我目前拥有的代码:
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');
}
这是目前的样子
我一直在努力让每个任务阶段相互叠加,
我读过 D3 Stacked bar chart with different stack level
和
https://bl.ocks.org/DimsumPanda/689368252f55179e12185e13c5ed1fee
找到了使其工作的方法:发布代码以供将来参考。
我解决这个问题的方法是遍历任务,并为每个任务添加一个组,然后在每个组中添加条。
这样我就不会丢失 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'));
});
此代码位于 VUEJs 框架内。
我正在努力创建堆叠条形图,但无法使用 D3 堆叠功能。 所以我尝试以不同的方式实现矩形的 y 位置和高度。
这是我的数据:
tasks: [
{
name:t1,
taskTotal:1000
taskStages: [
{
stageTotal: 200
},
{
stageTotal: 400
},{
stageTotal: 400
}
]
},
{
name:t2,
taskTotal:500
stages:[
{
stageTotal: 200
},
{
stageTotal: 300
}
],
}
]
我曾尝试为每个任务制定特定的比例,但没有成功。
每个条形的 x 位置都很好,我的问题是矩形的 y 位置和高度。
这是我目前拥有的代码:
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');
}
这是目前的样子
我一直在努力让每个任务阶段相互叠加, 我读过 D3 Stacked bar chart with different stack level
和 https://bl.ocks.org/DimsumPanda/689368252f55179e12185e13c5ed1fee
找到了使其工作的方法:发布代码以供将来参考。
我解决这个问题的方法是遍历任务,并为每个任务添加一个组,然后在每个组中添加条。
这样我就不会丢失 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'));
});