1

I have angular chart component which draws charts for time series data. The code is here:

  ChangeDetectionStrategy,
  Component,
  ElementRef,
  Input,
  OnDestroy,
  ViewChild,
  ViewEncapsulation,
} from '@angular/core';
import { notNullFilter } from '@app/lib/rxjs-not-null-filter';
import { AnychartCartesian } from '@app/shared/anychart/anychart.module';
import { ResizeObserver } from 'resize-observer';
import { combineLatest, BehaviorSubject, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

/**
 * Компонент для построения графиков с использованием anychart.
 */
@Component({
  selector: 'app-anychart',
  templateUrl: './anychart.component.html',
  styleUrls: ['./anychart.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
})
export class AppAnychartComponent implements OnDestroy {
  constructor() {
    combineLatest([
      this.elementRef$,
      this.anychartCartesian$,
      this.height$.pipe(notNullFilter()),
    ])
      .pipe(
        takeUntil(this.destroy$),
      )
      .subscribe(([ref, chart, height]) => {
        this.destroyPrevAnychart();
        if (ref !== null && chart !== null) {
          const el = ref.nativeElement;
          this.resizeObserver.observe(el);
          chart.height(height);
          chart.xScale('date-time'); // it makes chart stacked
          chart.credits().enabled(false);
          chart.container(el);
          chart.draw();
          this.prevChart = chart;
        }
      });
  }

  private readonly resizeObserver = new ResizeObserver(entries => {
    const chart = this.anychartCartesian$.getValue();
    if (chart === null) { return; }
    const widthPx: number = entries.reduce((acc, entry) => entry.contentRect.width || acc, 0);
    console.log('TODO: resize chart:', widthPx); // TODO: resize chart
  });

  private readonly elementRef$ = new BehaviorSubject<ElementRef<HTMLDivElement> | null>(null);
  @ViewChild('elRef') set elementRef(ref: ElementRef<HTMLDivElement> | undefined) {
    this.elementRef$.next(ref || null);
  }

  private readonly anychartCartesian$ = new BehaviorSubject<AnychartCartesian | null>(null);
  @Input() set chart(chart: AnychartCartesian) {
    this.anychartCartesian$.next(chart);
  }

  public readonly height$ = new BehaviorSubject<string | null>(null);
  @Input() set height(height: string) {
    this.height$.next(height);
  }

  private prevChart: AnychartCartesian | null = null;

  private readonly destroy$ = new Subject<void>();

  /**
   * @inheritDoc
   */
  public ngOnDestroy(): void {
    this.resizeObserver.disconnect();
    this.destroy$.next();
    this.destroy$.complete();
    this.destroyPrevAnychart();
  }

  private destroyPrevAnychart(): void {
    if (this.prevChart !== null) {
      this.prevChart.dispose();
      this.prevChart = null;

      // ensure clean up previous svg
      const ref = this.elementRef$.getValue();
      if (ref !== null) {
        const el = ref.nativeElement;
        while (el.firstChild) {
          el.removeChild(el.firstChild);
        }
      }
    }
  }
}

If I comment line chart.xScale('date-time'); chart looks like this normal bar chart

If I uncomment this line, chart becomes like this stacked bar chart

I've read docs but I have no idea why this happens. The question is how with date-time format of the x scale make normal bar chart as in the first screenshot? Thanks in advance!

UPD1. When I changed code from

const series1 = chart.colum(mapping1);

to

const series1 = chart.line(mapping1);`

as was proposed in answer, I've got chart which looks like this:

line chart

Dmitry Malugin
  • 882
  • 1
  • 7
  • 25

1 Answers1

0

This is expected behavior and it's not stacked mode. Let me explain. Every series has a point for the 1st March (for example 2020-03-01). If the scale is Ordinal (1st screenshot) it creates a category named "1 Mar". If the scale is dateTime, it becomes linear (not ordinal, the 2nd screenshot). In this case, every bar is placed strictly according to it's timestamp. But all bars have the same dateTime "2020-03-01". So, as a result, all they are placed in the same position. And looks like stacked, but it's not. The height of the bar is not a sum of all series values in this X coordinate. There are several available options to avoid it:

  1. Use the Ordinal scale which is the default
  2. Use dateTime scale, but switch column series to line or spline, it will increase readability
  3. Use dateTime scale, but create these series on separate charts.
AnyChart Support
  • 3,770
  • 1
  • 10
  • 16