График реального времени с использованием ng2-диаграмм с панорамированием и масштабированием - PullRequest
0 голосов
/ 12 марта 2020

Я новичок в использовании диаграмм, но я создаю компонент для создания диаграммы, используя ng2-диаграммы и данные (температуру), которые каждую секунду получают из службы MQTT. Он отлично работает, но в момент, когда данные обновляются каждую секунду, он получает что-то вроде этого:

Графики обновляются

Я хочу, чтобы каждый определенный кусок обновления, переместитесь вправо, оставив старые данные позади, но не удаляя их. Также хочу, чтобы пользователь мог, перетаскивая мышь влево или вправо, увидеть старые данные или новые.

Я попытался использовать диаграмму js -plugin-zoom, и она работает, но когда я масштабирую или панорамирование, данные исчезают. Также попытался использовать полосу прокрутки, и она просто появляется, но диаграмма никогда не расширяется, поэтому полоса прокрутки остается бесполезной.

Это мой код:

charts.component. html

            <div style="display: block">
                <canvas baseChart [datasets]="chartData" [labels]="chartLabels" [options]="chartOptions"
                    [legend]="chartLegend" [chartType]="chartType" (chartHover)="chartHovered($event)"
                    (chartClick)="chartClicked($event)">
                </canvas>
            </div>

charts.component.ts

import { Component, OnInit, Input } from '@angular/core';
import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
import { Label } from 'ng2-charts';
import 'chartjs-plugin-zoom';
import 'hammerjs';

@Component({
  selector: 'app-charts',
  templateUrl: './charts.component.html',
  styleUrls: ['./charts.component.css']
})
export class ChartsComponent implements OnInit {

  @Input() typeChart: ChartType;
  @Input() typeLabel: Label;

  @Input() set chartAppOptions(options) {
    if (this.typeLabel) { this.typeLabel = this.updateLabel(this.typeLabel); }
    for (const option of options) {
      // console.log(option);
      this.addValuesChartData(option);
    }
  }

  date = new Date();

  chartOptions: ChartOptions = {
    responsive: true,
    // We use these empty structures as placeholders for dynamic theming.
    scales: { xAxes: [{ticks: {beginAtZero: true}}], yAxes: [{}] },
    plugins: {
      zoom: {
        pan: {
          enabled: true,
          mode: 'xy',
        },
        zoom: {
          enabled: true,
          mode: 'xy',
        },
      }
    }
  };
  chartLabels: Label[] = [];
  chartType: ChartType = 'line';
  chartLegend = true;

  chartData: ChartDataSets[] = [
    {data: [], label: '' }
  ];

  constructor() {}

  ngOnInit() {
    if (this.typeChart) { this.chartType = this.typeChart; }
  }

  updateLabel(label: Label) {
    let labelString: Label;
    if (!label) {
      label = 'date';
    }
    switch (label) {
      case 'date':
        labelString =
        `${this.date.getDate()}/${this.date.getMonth() + 1}/${this.date.getFullYear()} ${this.date.getHours()}:${this.date.getMinutes()}`;
        break;
      default:
        labelString = label;
        break;
      }
    return labelString;
  }

  addValuesChartData({name, value}) {
    const emptyChartData = this.findInArray(this.chartData, '', 'label');
    const notFound = -1;
    if (!value) {
      value = 0;
    }
    if (emptyChartData !== notFound) {
      this.chartData[emptyChartData].label = name;
    }
    const positionChartData = this.findInArray(this.chartData, name, 'label');
    if (positionChartData === notFound) {
      const newChartData: ChartDataSets = {
        data: [],
        label: name
      };
      this.chartData.push(newChartData);
      const newChartDataLabelPosition = this.findInArray(this.chartData, name, 'label');
      this.chartData[newChartDataLabelPosition].data.push(value);
    } else {
      this.chartData[positionChartData].data.push(value);
    }
    const lengthChartData = this.chartData[0].data.length;
    const lenghtChartLabels = this.chartLabels.length;
    if (lengthChartData !== lenghtChartLabels) {
      this.chartLabels.push(this.typeLabel);
    }
  }

  findInArray(arr, name, extension) {
    return arr.findIndex(item => item[extension] === name);
  }

  // events
  chartClicked({ event, active }: { event: MouseEvent, active: {}[] }): void {}

  chartHovered({ event, active }: { event: MouseEvent, active: {}[] }): void {}

}

Вот как Звоню компонент со страницы:

html

<div>
    <app-charts [chartAppOptions]="chartAppOptions4" typeLabel="date" typeChart="line"></app-charts>
</div>

ц

import { Component } from '@angular/core';
import { MqttSvc } from 'src/app/services/mqtt.service';

@Component({
  selector: 'app-chart',
  templateUrl: './chart.component.html',
  styleUrls: ['./chart.component.css']
})
export class ChartComponent {

  chartAppOptions4 = [
    {
      name: 'Temperatura',
      value: 0,
    },
    {
      name: 'Temperatura * 2',
      value: 0,
    },
    {
      name: 'Temperatura * 3',
      value: 0,
    },
    {
      name: 'Temperatura * 4',
      value: 0,
    }
  ];

  subscribe: any;

  constructor( private mqttSvc: MqttSvc) {}

  connect() {
    console.log('connected');
    this.subscribe = this.mqttSvc.connect(SERVIDOR/API).subscribe(data => {
      const temp = Number(data.payload.toString());
      console.log(temp);
      this.changeChartAppOptions(temp);
    });
  }

  disconnect() {
    console.log('disconnect');
    this.subscribe.unsubscribe();
  }

  changeChartAppOptions(temp: number) {

    for (let i = 0, n = this.chartAppOptions4.length; i < n; i++) {
        const j = i + 1;
        if (this.chartAppOptions4[i].value !== temp * j) {
          this.chartAppOptions4 = [
            {
              name: 'Temperatura',
              value: temp,
            },
            {
              name: 'Temperatura * ' + j,
              value: temp * j,
            },
            {
              name: 'Temperatura * ' + j,
              value: temp * j,
            },
            {
              name: 'Temperatura * ' + j,
              value: temp * j,
            }
          ];
        }
      }
  }

}

...