我正在学习D3js,以下脚本仅渲染包含垂直线的SVG。我试图了解我在这里做错了什么。
我有一个名为Fight的数据项,其中包含一些数据,包括一个属性,该属性可将游戏的日志文件中的所有损坏事件获取并将其插入type类型的对象中{ time: number, damage: number }
。
时间以毫秒为单位。
export class GraphComponent implements OnInit {
fight: Fight;
svg: any;
g: any;
x: any;
y: any;
constructor(
private readonly graphService: GraphService,
private readonly hostElement: ElementRef
) { }
ngOnInit(): void {
this.graphInit();
this
.graphService
.fight
.subscribe({
next: fight => {
this.fight = fight;
this.graph();
},
error: error => {
console.error(error);
}
});
}
graphInit(): void {
this.svg =
d3
.select(this.hostElement.nativeElement)
.append('svg')
.attr('width', '100%')
.attr('height', '100%')
.attr('viewBox', [0, 0, 200, 100].join(' '));
}
graph(): void {
const data = this.fight.damage;
const width = this.fight.timeElapsedMs;
const height = this.fight.maxDamage + (this.fight.maxDamage * 0.05);
// X and Y Axis for area charts
this.x =
d3
.scaleLinear()
.domain(d3.extent(data, d => d.time))
.range([0, width]);
this
.svg
.append('g')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(this.x));
this.y =
d3
.scaleLinear()
.domain(d3.extent(data, d => d.damage))
.range([height, 0]);
this
.svg
.append('g')
.call(d3.axisLeft(this.y));
this
.svg
.append('path')
.datum(data)
.attr('fill', 'none')
.attr('stroke', '#a80000')
.attr('stroke-width', 1.5)
.attr('d',
d3
.line()
.x((d: any) => this.x(d.time))
.y((d: any) => this.y(d.damage))
);
}
}
完整的Stackblitz:https ://stackblitz.com/github/xoriworgv ? file = src/app/shared/components/graph/graph.component.ts
这是一个电子应用程序,所以我看看是否可以输入一些虚拟数据并使它工作。
我用Stackblitz链接扣除了您的问题,其中包含一些示例数据。
问题在于您处理数据的方式。d3.line()
需要一个n
点数组,每个点都带有x
和y
坐标。您只给了它fight.damage
,它是一个数字数组。我为您创建了一个函数zip
,您可以轻松地将它与TypeScript一起使用,以帮助转换数据。
完成此操作后,您将看到的不仅仅是一行!
const graph = (fight) => {
const svg =
d3.select('svg')
.attr('width', '400')
.attr('height', '250')
.attr('viewBox', [0, 0, 200, 100].join(' '));
const line =
d3
.line()
.x((d) => x(d.time))
.y((d) => y(d.damage));
const rawData = zip(fight.time, fight.damage);
const data = rawData.map(([time, damage]) => ({
time: time,
damage: damage,
}));
const width = fight.timeElapsedMs;
const height = fight.maxDamage + (fight.maxDamage * 0.05);
// X and Y Axis for area charts
const x =
d3.scaleLinear()
.domain(d3.extent(fight.time))
.range([0, width]);
svg
.append('g')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(x));
const y =
d3
.scaleLinear()
.domain(d3.extent(fight.damage))
.range([height, 0]);
svg
.append('g')
.call(d3.axisLeft(y));
svg
.append('path')
.datum(data)
.attr('fill', 'none')
.attr('stroke', '#a80000')
.attr('stroke-width', 1.5)
.attr('d', line);
};
const fight = {
damage: [50, 100, 50, 150],
time: [100, 200, 300, 400],
timeElapsedMs: 500,
maxDamage: 100,
};
/**
* zip is a javascript equivalent of the python zip function
*
* Example:
* zip([1, 2, 3], [11, 22, 33]) => [[1, 11], [2, 22], [3, 33]]
*
* @param {T[][]} rows An array of the rows to zip
* @returns {T[][]} the zipped array
*/
//function zip<T>(...rows: T[][]): T[][] {
function zip(...rows) {
return rows[0].map((_, col) => rows.map(row => row[col]));
}
graph(fight);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句