#javascript #angular #typescript #charts #chart.js
#javascript #angular #typescript #Диаграммы #chart.js
Вопрос:
Я использую диаграмму.JS для создания гистограммы, но у меня возникают проблемы с использованием двух объектов JSON, которые я создал, чтобы сделать диаграмму динамической. Я не уверен, как я должен это делать, но объекты могут изменять значения, и я хочу, чтобы диаграмма поддерживала это.
Это мой объект для меток:
0: {labelName: "Plan Miles"}
1: {labelName: "Actual Miles"}
2: {labelName: "Route Variance"}
и у меня есть аналогичный объект для моих наборов данных.
Значения объекта могут быть любыми, поэтому я хочу сделать свою диаграмму динамической, чтобы поддержать это.
Что я могу изменить в своем коде, чтобы это произошло?
Я хочу удалить вторую и третью точки данных и иметь только один набор данных, который будет поддерживать несколько столбцов на диаграмме. Поэтому я хотел бы выполнить цикл или сопоставить как объект label JSON, так и объект data JSON, чтобы создать диаграмму.
charts.component.ts
export class ChartsComponent implements OnInit {
canvas: any;
ctx: any;
ChartData: any;
labelNames: any;
constructor() {}
ngOnInit(): void {
// Charts
this.canvas = document.getElementById('viewChart');
this.ctx = this.canvas.getContext('2d');
this.ChartData = JSON.parse(localStorage.getItem('ChartData'));
const data = this.ChartData;
//Label Object for Chart
this.labelNames = JSON.parse(localStorage.getItem('LabelNames'));
const labelNames = this.labelNames;
const labelObject = [];
// tslint:disable-next-line: prefer-for-of
for(let i = 0; i < labelNames.length; i ) {
const obj = labelNames[i].propertyName;
labelObject.push({labelName: obj});
}
const newLabelObject = labelObject.slice(3, 5 1)
console.log('Labels: ', newLabelObject);
// tslint:disable-next-line: only-arrow-functions
const barLabel = newLabelObject.map(function (e) {
return e[1];
})
// tslint:disable-next-line: only-arrow-functions
const driverLabel = data.map(function (e: any[]) {
return e[1];
});
// tslint:disable-next-line: only-arrow-functions
const firstDataPoint = data.map(function (e: any[]) {
return e[3];
});
// tslint:disable-next-line: only-arrow-functions
const secondDataPoint = data.map(function (e: any[]) {
return e[4];
});
// tslint:disable-next-line: only-arrow-functions
const thirdDataPoint = data.map(function (e: any[]) {
return e[5];
});
const viewChart = new Chart(this.ctx, {
type: 'bar',
data: {
labels: driverLabel,
datasets: [
{
label: `newLabelObject`,
data: firstDataPoint,
backgroundColor: 'rgb(34, 167, 240)',
borderWidth: 1
},
{
label: 'Actual Miles',
data: secondDataPoint,
backgroundColor: 'rgb(240, 52, 52)',
borderWidth: 1
},
{
label: 'Route Variance',
data: thirdDataPoint,
backgroundColor: 'rgba(254, 241, 96, 1)',
borderWidth: 1
}
]
},
Ответ №1:
если возможно, я думаю, было бы лучше, если бы вы использовали версию chart, которая полностью совместима с вашей версией Angular, например:
Но если вам действительно нужно использовать эту версию, вы можете создать массив с обоими значениями и выполнить итерацию этого массива для создания своих значений:
let labels = [{label: "A"}, {label: "B"}, {label: "C"}, {label: "D"}, {label: "E"}];
let values = [{value: 1}, {value: 2}, {value: 3}, {value: 4}, {value: 5}];
let finalArray = [];
labels.forEach((currentLabel, index) => {
finalArray.push({ label: currentLabel.label, value: values[index].value});
});
/* finalArray will be:
[
{label: "A", value: 1}
{label: "B", value: 2}
{label: "C", value: 3}
{label: "D", value: 4}
{label: "E", value: 5}
];
*/
Комментарии:
1. но что, если мои значения структурированы как [{ValueA: 1A ValueB: 2A}}, где каждый объект имеет несколько значений? как мне добавить это в мой конечный массив, чтобы у меня мог быть только один набор данных? @priscillaanjos
2. Также как я мог бы использовать это, если метки принимают только строковые значения?
Ответ №2:
chart.js документация, вероятно, является лучшим ресурсом с точки зрения структурирования данных для ввода. Насколько я понимаю ваш вопрос, вы хотите переключаться между гистограммами на одной и той же диаграмме, верно? Я собрал небольшой пример использования stackblitz chart.js в angular для этого нужно. По сути, объект конфигурации диаграммы определяет, что будет нарисовано. Это необходимо поменять местами в зависимости от данных, которые вы хотите отобразить, и повторно отобразить. Надеюсь, это полезно / актуально. Прошу прощения, если я неправильно понял ваш вопрос.
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { Chart } from 'chart.js';
const dataset1 = {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
}]
};
const dataset2 = {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of People',
data: [3, 5, 2, 12, 19, 3],
}]
};
@Component({
selector: 'app-chart',
templateUrl: './chart.component.html',
styleUrls: ['./chart.component.css']
})
export class ChartComponent implements OnInit {
chart: Chart;
@ViewChild('graph', { static: true })
graph: ElementRef;
ctx: CanvasRenderingContext2D;
currentDataSet = dataset1;
constructor() {}
ngOnInit() {
this.ctx = (<HTMLCanvasElement>this.graph.nativeElement).getContext(
'2d',
);
this.renderChart();
}
renderChart(){
this.chart = new Chart(this.ctx, this.chartConfig);
}
pick(dataSet){
this.currentDataSet = dataSet === 1 ? dataset1 : dataset2;
this.renderChart();
}
get chartConfig(): Chart.ChartConfiguration {
return {
type: 'bar',
data: this.currentDataSet,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
}
}
}