Использование двух объектов JSON для создания диаграммы.Динамическая гистограмма JS в Typescript / Angular

#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
                          }
                      }]
                  }
              }
          }
  }
}