【发布时间】:2021-09-26 23:13:09
【问题描述】:
我的 Angular 项目的 csv 文件中有以下数据,该文件还导入了 D3.js 库:
group,Nitrogen,normal,stress
banana,12,1,13
poacee,6,6,33
sorgho,11,28,12
triticum,19,6,1
我在打字稿文件中也有以下代码来显示堆叠条:
import { Component, OnInit } from '@angular/core';
import * as d3 from 'd3';
@Component({
selector: 'app-stacked-bar',
templateUrl: './stacked-bar.component.html',
styleUrls: ['./stacked-bar.component.css']
})
export class StackedBarComponent implements OnInit {
data = [
{"group": "banana", "Nitrogen": "12", "normal": "1", "stress": "13"},
{"group": "poacee", "Nitrogen": "6", "normal": "6", "stress": "33"},
{"group": "sorgho", "Nitrogen": "11", "normal": "28", "stress": "12"},
{"group": "triticum", "Nitrogen": "19", "normal": "6", "stress": "1"}
];
svg: any;
margin = 50;
width = 750 - (this.margin * 2);
height = 400 - (this.margin * 2);
ngOnInit(): void {
this.createSvg();
this.drawBars(this.data);
}
createSvg(): void {
this.svg = d3.select("figure#stacked-bar")
.append("svg")
.attr("width", this.width + (this.margin * 2))
.attr("height", this.height + (this.margin * 2))
.append("g")
.attr("transform", "translate(" + this.margin + "," + this.margin + ")");
}
drawBars(data): void {
// List of subgroups - Header of the csv file.
// ["Nitrogen", "normal", "stress"]
const subgroups = data.columns.slice(1);
// List of groups - Value of the first column, called group.
const groups = data.map(d => (d.group));
// Create the X-axis band scale.
const x = d3.scaleBand()
.domain(groups)
.range([0, this.width])
//.domain(data.map(d => d.groups))
.padding(0.2);
// Draw the X-axis on the DOM.
this.svg.append("g")
.attr("transform", "translate(0," + this.height + ")")
.call(d3.axisBottom(x).tickSizeOuter(0));
// Create the Y-axis band scale.
const y = d3.scaleLinear()
.domain([0, 60])
.range([this.height, 0]);
// Draw the Y-axis on the DOM.
this.svg.append("g")
.call(d3.axisLeft(y));
// color palette = one color per subgroup
const color = d3.scaleOrdinal()
.domain(subgroups)
.range(['#e41a1c','#377eb8','#4daf4a']);
// Stack the data per subgroup.
const stackedData = d3.stack()
.keys(subgroups)
(data);
// Create and fill the bars.
this.svg.append("g")
.selectAll("g")
.data(stackedData)
.join("g")
.attr("fill", d => color(d.key))
.selectAll("rect")
.data(d => d)
.join("rect")
.attr("x", d => x(d.data.group))
.attr("y", d => y(d[1]))
.attr("height", d => y(d[0]) - y(d[1]))
.attr("width", x.bandwidth());
}
}
但我只得到一个空的情节。当我检查页面时,我有这个控制台错误:
TypeError:无法读取未定义的属性“切片”
由于data 中的某些类型不明确,无法应用slice 方法,但是当我在代码中复制并粘贴["Nitrogen", "normal", "stress"] 代替subgroups 时,一切正常!
有人可以帮我解决这个问题吗?
附言图表应该是这样的:
【问题讨论】:
-
如果是运行时错误,则与 TypeScript 类型无关。 TypeScript 类型是一个编译时的概念(除了枚举,它在运行时作为值存在)。
-
你能看到这个运行时错误的原因吗?在我见过的所有示例中,
d => y(d[0]) - y(d[1])返回一个数字并且它可以正常工作。在这里,它不返回一个数字... -
对于
.attr("x"...,您使用d作为对象;但是对于.attr("height"...,您使用d作为数组。设置y和height时是否需要引用d的属性? -
@Robin Mackenzie 我认为匿名函数(使用 d)基本上递归地减去每个条的高度,因此是一个数组。我编辑了我的问题并添加了堆叠条形图应该是什么样子的图像。您可以看到,例如,对于香蕉,我们需要一个长度为 12(红色)和 1(蓝色)和 13(绿色)的条形。请在我的帖子中查看新图像。我希望你能看到问题...
-
@CatarinaRuna - 很遗憾,我做不到,但这并不奇怪,因为我不使用 Angular 并且我没有使用过
d3。 :-D 我会将简洁的箭头函数更改为d => { /*newline*/ const v1 = y(d[0]), v2 = y(d[1]), retVal = v1 - v2; /*newline*/ return retVal; /*newline*/},在return上放置一个断点,然后查看v1、v2和retVal的值。
标签: javascript angular typescript d3.js