简体   繁体   中英

Loosing a Timeserie when zooming in AMCharts

When I am zooming in the graph, the serie2 disappears...also if I zoom by picking the cursor from the right....BUT from the left the zoom is working fine !!

I am expecting to see the 2 series in any cases but it seems that sometimes it's not...

See my screenshot

Any idea why?

My component looks like this:

import { Component, NgZone, OnDestroy, OnInit } from '@angular/core';
import * as am4core from '@amcharts/amcharts4/core';
import * as am4charts from '@amcharts/amcharts4/charts';
import am4themes_animated from '@amcharts/amcharts4/themes/animated';
import {DayAheadService} from '../../_services/day-ahead.service';
import { Subscription } from 'rxjs';

am4core.useTheme(am4themes_animated);

@Component({
  providers: [DayAheadService],
  selector: 'app-max',
  templateUrl: './maximize.component.html',
  styleUrls: ['./maximize.component.scss']
})
export class MaximizeComponent implements OnDestroy {
  private chart: am4charts.XYChart;
  private subscription: Subscription;
  clearingsSell: any = [];
  clearingsBuy: any = [];
  constructor(
    private dayAheadService: DayAheadService,
    private zone: NgZone) {}

    ngOnInit() {

    }

    ngAfterViewInit() {
    this.zone.runOutsideAngular(() => {
      let chart = am4core.create('chartdiv', am4charts.XYChart);
      chart.paddingRight = 20;
      let data1 = [];
      let data2 = [];
      this.subscription = this.dayAheadService.requestAggClearingsMada('2019-01-01', 'asset' , '2019-01-19' ).subscribe(x => {
        this.clearingsSell = x.filter(f => f.direction === 'Sell');
        this.clearingsBuy = x.filter(f => f.direction === 'Buy');
        for (let i = 1; i < this.clearingsSell.length; i++) {
          for (let j = 0; j < 24; j++) {
              data1.push({ category : 'Sell', date: new Date(2019, 0, i, j).setHours(j), value1: this.clearingsSell[i].profilesData[j].price });
          }
        }
        for (let i = 1; i < this.clearingsBuy.length; i++) {
          for (let j = 0; j < 24; j++) {
              data2.push({ category : 'Buy', date: new Date(2019, 0, i, j).setHours(j), value2: this.clearingsBuy[i].profilesData[j].price });
          }
        }
        chart.data = data1.concat(data2);
        console.log(chart.data);
        });

        chart.dateFormatter.inputDateFormat = 'YY-MM-DD HH';
        const dateAxis = chart.xAxes.push(new am4charts.DateAxis());
        dateAxis.renderer.minGridDistance = 90;
        dateAxis.startLocation = 0.5;
        dateAxis.endLocation = 0.5;
        const valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
        valueAxis.tooltip.disabled = true;
        const series = chart.series.push(new am4charts.StepLineSeries());
        series.dataFields.dateX = 'date';
        series.name = 'Sell Vol.';
        series.dataFields.valueY = 'value1';
        series.tooltipText = '[#000]{valueY.value}[/]';
        series.tooltip.background.fill = am4core.color('#FFF');
        series.tooltip.getStrokeFromObject = true;
        series.tooltip.background.strokeWidth = 3;
        series.tooltip.getFillFromObject = false;
        series.fillOpacity = 0.6;
        series.strokeWidth = 2;
        series.stacked = true;
        const series2 = chart.series.push(new am4charts.StepLineSeries());
        series2.name = 'Buy Vol.';
        series2.dataFields.dateX = 'date';
        series2.dataFields.valueY = 'value2';
        series2.tooltipText = '[#000]{valueY.value}[/]';
        series2.tooltip.background.fill = am4core.color('#FFF');
        series2.tooltip.getFillFromObject = false;
        series2.tooltip.getStrokeFromObject = true;
        series2.tooltip.background.strokeWidth = 3;
        series2.sequencedInterpolation = true;
        series2.fillOpacity = 0.6;
        series2.stacked = true;
        series2.strokeWidth = 2;
        // Add scrollbar
        chart.scrollbarX = new am4charts.XYChartScrollbar();
        // Add cursor
        chart.cursor = new am4charts.XYCursor();
        chart.cursor.xAxis = dateAxis;
        chart.cursor.snapToSeries = series;
        // Add a legend
        chart.legend = new am4charts.Legend();
        chart.legend.position = 'top';
    });
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
    this.zone.runOutsideAngular(() => {
      if (this.chart) {
        this.chart.dispose();
      }
    });
  }
}

AmCharts expects date-based data to be grouped by date, not concatenated, otherwise you'll run into undefined behavior, such as your zooming issue. You'll need to rewrite your subscribe method to aggregate everything correctly:

clearingsSell = x.filter(f => f.direction === "Sell");
clearingsBuy = x.filter(f => f.direction === "Buy");
//store everything into an object with the date as the key
for (let i = 1; i < clearingsSell.length; i++) {
  for (let j = 0; j < 24; j++) {
    let date = new Date(2019, 0, i, j).setHours(j);
    data[date] = {
      date: date,
      value1: clearingsSell[i].profilesData[j].price
    }
  }
}
for (let i = 1; i < clearingsBuy.length; i++) {
  for (let j = 0; j < 24; j++) {
    let date = new Date(2019, 0, i, j).setHours(j);
    if (data[date] === undefined) {
      data[date] = {date: date};
    }
    data[date].value2 = clearingsBuy[i].profilesData[j].price
  }
}
//convert grouped data into array, iterating by date
chart.data = Object.keys(data).map(function(date) { 
  return data[date];
})

Note that I removed the categories as they didn't appear to be relevant to your chart setup. Here's a simplified demo based off your code:

 let chart = am4core.create("chartdiv", am4charts.XYChart); chart.paddingRight = 20; let data = {}; let data1 = []; let data2 = []; x = getData(); //--- modified subscribe code --- clearingsSell = x.filter(f => f.direction === "Sell"); clearingsBuy = x.filter(f => f.direction === "Buy"); //store everything into an object with the date as the key for (let i = 1; i < clearingsSell.length; i++) { for (let j = 0; j < 24; j++) { let date = new Date(2019, 0, i, j).setHours(j); data[date] = { date: date, value1: clearingsSell[i].profilesData[j].price } } } for (let i = 1; i < clearingsBuy.length; i++) { for (let j = 0; j < 24; j++) { let date = new Date(2019, 0, i, j).setHours(j); if (data[date] === undefined) { data[date] = {date: date}; } data[date].value2 = clearingsBuy[i].profilesData[j].price } } //convert grouped data into array, iterating by date chart.data = Object.keys(data).map(function(date) { return data[date]; }); // --- end modified subscribe code -- chart.dateFormatter.inputDateFormat = "YY-MM-DD HH"; const dateAxis = chart.xAxes.push(new am4charts.DateAxis()); dateAxis.renderer.minGridDistance = 90; dateAxis.startLocation = 0.5; dateAxis.endLocation = 0.5; const valueAxis = chart.yAxes.push(new am4charts.ValueAxis()); valueAxis.tooltip.disabled = true; const series = chart.series.push(new am4charts.StepLineSeries()); series.dataFields.dateX = "date"; series.name = "Sell Vol."; series.dataFields.valueY = "value1"; series.tooltipText = "[#000]{valueY.value}[/]"; series.tooltip.background.fill = am4core.color("#FFF"); series.tooltip.getStrokeFromObject = true; series.tooltip.background.strokeWidth = 3; series.tooltip.getFillFromObject = false; series.fillOpacity = 0.6; series.strokeWidth = 2; series.stacked = true; const series2 = chart.series.push(new am4charts.StepLineSeries()); series2.name = "Buy Vol."; series2.dataFields.dateX = "date"; series2.dataFields.valueY = "value2"; series2.tooltipText = "[#000]{valueY.value}[/]"; series2.tooltip.background.fill = am4core.color("#FFF"); series2.tooltip.getFillFromObject = false; series2.tooltip.getStrokeFromObject = true; series2.tooltip.background.strokeWidth = 3; series2.sequencedInterpolation = true; series2.fillOpacity = 0.6; series2.stacked = true; series2.strokeWidth = 2; // Add scrollbar chart.scrollbarX = new am4charts.XYChartScrollbar(); // Add cursor chart.cursor = new am4charts.XYCursor(); chart.cursor.xAxis = dateAxis; chart.cursor.snapToSeries = series; // Add a legend chart.legend = new am4charts.Legend(); chart.legend.position = "top"; function getData() { return [ { direction: "Buy", profilesData: [ { price: 14 }, { price: 12 }, { price: 16 }, { price: 13 }, { price: 10 }, { price: 10 }, { price: 18 }, { price: 13 }, { price: 17 }, { price: 12 }, { price: 18 }, { price: 10 }, { price: 10 }, { price: 17 }, { price: 17 }, { price: 20 }, { price: 13 }, { price: 17 }, { price: 13 }, { price: 12 }, { price: 16 }, { price: 16 }, { price: 13 }, { price: 11 } ] }, { direction: "Buy", profilesData: [ { price: 14 }, { price: 15 }, { price: 13 }, { price: 14 }, { price: 18 }, { price: 10 }, { price: 10 }, { price: 18 }, { price: 17 }, { price: 15 }, { price: 17 }, { price: 19 }, { price: 12 }, { price: 20 }, { price: 11 }, { price: 16 }, { price: 17 }, { price: 15 }, { price: 13 }, { price: 10 }, { price: 18 }, { price: 10 }, { price: 19 }, { price: 14 } ] }, { direction: "Sell", profilesData: [ { price: 13 }, { price: 11 }, { price: 12 }, { price: 6 }, { price: 8 }, { price: 9 }, { price: 13 }, { price: 15 }, { price: 13 }, { price: 11 }, { price: 12 }, { price: 7 }, { price: 8 }, { price: 10 }, { price: 6 }, { price: 5 }, { price: 5 }, { price: 7 }, { price: 10 }, { price: 13 }, { price: 10 }, { price: 5 }, { price: 5 }, { price: 6 } ] }, { direction: "Sell", profilesData: [ { price: 11 }, { price: 7 }, { price: 5 }, { price: 12 }, { price: 7 }, { price: 5 }, { price: 13 }, { price: 6 }, { price: 12 }, { price: 11 }, { price: 11 }, { price: 10 }, { price: 5 }, { price: 12 }, { price: 10 }, { price: 7 }, { price: 7 }, { price: 7 }, { price: 14 }, { price: 14 }, { price: 11 }, { price: 12 }, { price: 13 }, { price: 8 } ] } ]; }
 body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; } #chartdiv { width: 100%; height: 450px; }
 <script src="//www.amcharts.com/lib/4/core.js"></script> <script src="//www.amcharts.com/lib/4/charts.js"></script> <script src="//www.amcharts.com/lib/4/themes/animated.js"></script> <div id="chartdiv"></div>

Your dates need to be in ascending order for it to work with a DateAxis. Your dates are descending, which can lead into issues like the scrollbar breaking. Just call reverse() on your array:

component.ts

let data = [
    {
        "value": 27.75,
        "date": new Date(2019, 0, 31)
    },
    {
        "value": 27.77,
        "date": new Date(2019, 0, 30)
    },
    {
        "value":  27.79,
        "date": new Date(2019, 0, 29)
    },
    {
        "value": 27.81,
        "date": new Date(2019, 0, 28)
    },
    {
        "value": 27.78,
        "date": new Date(2019, 0, 27)
    }
].reverse();

let chart = am4core.create("chart", am4charts.XYChart);
chart.data = data;
let xAxis = chart.xAxes.push(new am4charts.DateAxis());
let yAxis = chart.yAxes.push(new am4charts.ValueAxis())

xAxis.dataFields.category = "date";
xAxis.title.text = "Date";

let series = chart.series.push(new am4charts.LineSeries())
let bullet = series.bullets.push(new am4charts.CircleBullet())
series.dataFields.dateX = "date";
series.dataFields.valueY = "value";
series.tooltipText = "{valueY}"
chart.cursor = new am4charts.XYCursor();
series.name = "Value";
series.strokeWidth = 2;
chart.scrollbarX = new am4core.Scrollbar();

component.css

div {
  width: 100%;
  height: 300px;
}

component.html

<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<div id="chart"></div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM