This demo uses imperative chart updates. The generated code is a faithful Angular translation: open it in CodeSandbox to run and tweak.

import { Component, AfterViewInit, OnDestroy, ViewChild } from '@angular/core';
import {
  ChartComponent,
  ApexAxisChartSeries,
  ApexNonAxisChartSeries,
  ApexChart,
  ApexXAxis,
  ApexYAxis,
  ApexTitleSubtitle,
  ApexDataLabels,
  ApexStroke,
  ApexFill,
  ApexLegend,
  ApexTooltip,
  ApexMarkers,
  ApexPlotOptions,
  ApexResponsive,
  ApexGrid,
  ApexAnnotations,
  ApexStates,
  ApexTheme,
  NgApexchartsModule,
} from 'ng-apexcharts';

export type ChartOptions = {
  series?: ApexAxisChartSeries | ApexNonAxisChartSeries;
  chart?: ApexChart;
  xaxis?: ApexXAxis;
  yaxis?: ApexYAxis | ApexYAxis[];
  title?: ApexTitleSubtitle;
  subtitle?: ApexTitleSubtitle;
  dataLabels?: ApexDataLabels;
  stroke?: ApexStroke;
  fill?: ApexFill;
  legend?: ApexLegend;
  tooltip?: ApexTooltip;
  markers?: ApexMarkers;
  plotOptions?: ApexPlotOptions;
  responsive?: ApexResponsive[];
  grid?: ApexGrid;
  annotations?: ApexAnnotations;
  states?: ApexStates;
  theme?: ApexTheme;
  colors?: string[];
  labels?: any;
};

@Component({
  selector: 'app-chart',
  standalone: true,
  imports: [NgApexchartsModule],
  templateUrl: './chart.component.html',
})
export class AppChart implements AfterViewInit, OnDestroy {
  @ViewChild('chart') chart!: ChartComponent;
  private TOTAL_POINTS: any = 500000;

  private generateData = (count: any): any => {
          var data = new Array(count)
          var startTime = new Date('2010-01-01T00:00:00Z').getTime()
          var step = 60 * 1000 // 1 minute
          var y = 100
          for (var i = 0; i < count; i++) {
            // Random walk with periodic components — gives visible structure at
            // multiple zoom levels (slow trend + faster cycle + noise).
            y +=
              (Math.random() - 0.5) * 2 +
              Math.sin(i / 5000) * 0.05 +
              Math.cos(i / 1200) * 0.02
            data[i] = [startTime + i * step, +y.toFixed(3)]
          }
          return data
        };

  private seriesData: any = this.generateData(this.TOTAL_POINTS);

  private lastRenderMs: any = 0;

  private lastZoomLabel: any = 'full range';

  private fmt = (ts: any): any => {
          var d = new Date(ts)
          return (
            d.getFullYear() +
            '-' +
            String(d.getMonth() + 1).padStart(2, '0') +
            '-' +
            String(d.getDate()).padStart(2, '0')
          )
        };

  private updateStats = (chart: any): any => {
          var statsEl = document.getElementById('stats')
          if (!statsEl || !chart || !chart.w) return
          var drawn = (chart.w.globals.series[0] || []).length
          statsEl.innerHTML =
            'Raw points: <b>' +
            this.TOTAL_POINTS.toLocaleString() +
            '</b> &nbsp;·&nbsp; Currently drawn: <b>' +
            drawn.toLocaleString() +
            '</b> &nbsp;·&nbsp; Window: <b>' +
            this.lastZoomLabel +
            '</b> &nbsp;·&nbsp; Render: <b>' +
            this.lastRenderMs +
            ' ms</b>'
        };

  private rebuild = (): any => {
          var enabled = document.getElementById('toggleReducer').checked
          var targetPoints = parseInt(document.getElementById('targetPoints').value, 10)
  
          this.chartOptions.chart.dataReducer.enabled = enabled
          this.chartOptions.chart.dataReducer.targetPoints = targetPoints
          this.chartOptions.subtitle.text = enabled
            ? 'LTTB downsampling enabled — drawing ~' +
              targetPoints.toLocaleString() +
              ' points'
            : 'Downsampling disabled — drawing every raw point'
  
          var t2 = performance.now()
          this.chart.destroy()
          this.chart = new ApexCharts(document.querySelector('#chart'), this.chartOptions)
          this.chart.render().then(function () {
            this.lastRenderMs = Math.round(performance.now() - t2)
            this.updateStats(this.chart)
          })
        };

  public chartOptions: Partial<ChartOptions> = {
          series: [{ name: 'Sensor reading', data: this.seriesData }],
          chart: {
            height: 460,
            type: 'line',
            animations: { enabled: false },
            zoom: { enabled: true, type: 'x', autoScaleYaxis: true },
            toolbar: { autoSelected: 'zoom' },
            dataReducer: {
              enabled: true,
              algorithm: 'lttb',
              targetPoints: 500,
              threshold: 1000,
            },
            events: {
              zoomed: (chartCtx, args) => {
                var xaxis = args && args.xaxis
                this.lastZoomLabel =
                  xaxis && xaxis.min && xaxis.max
                    ? this.fmt(xaxis.min) + ' → ' + this.fmt(xaxis.max)
                    : 'full range'
                requestAnimationFrame(function () {
                  this.updateStats(chartCtx)
                })
              }        beforeResetZoom: () => {
                this.lastZoomLabel = 'full range'
              },
            },
          },
          stroke: { curve: 'straight', width: 1 },
          dataLabels: { enabled: false },
          markers: { size: 0 },
          title: {
            text: 'Line chart — 500,000 raw datapoints',
            align: 'left',
          },
          subtitle: {
            text: 'LTTB downsampling enabled — zoom in to re-sample the raw series at higher resolution within the visible window',
            align: 'left',
          },
          xaxis: {
            type: 'datetime',
            labels: { datetimeUTC: false },
          },
          yaxis: {
            labels: {
              formatter: (val) => {
                return val.toFixed(2)
              },
            },
          },
          tooltip: { x: { format: 'yyyy-MM-dd HH:mm' } },
        };
  ngAfterViewInit() {
    (window as any).ApexCharts.setLicense('APEX-eyJpc3N1ZURhdGUiOiIyMDI2LTA0LTE2IiwiZXhwaXJ5RGF0ZSI6IjIwNTItMDQtMTciLCJwbGFuIjoiZW50ZXJwcmlzZSIsImRvbWFpbnMiOlsiYXBleGNoYXJ0cy5jb20iLCIxMjcuMC4wLjEiXX0=');

    var this.chartOptions = {
            series: [{ name: 'Sensor reading', data: this.seriesData }],
            chart: {
              height: 460,
              type: 'line',
              animations: { enabled: false },
              zoom: { enabled: true, type: 'x', autoScaleYaxis: true },
              toolbar: { autoSelected: 'zoom' },
              dataReducer: {
                enabled: true,
                algorithm: 'lttb',
                targetPoints: 500,
                threshold: 1000,
              },
              events: {
                zoomed: (chartCtx, args) => {
                  var xaxis = args && args.xaxis
                  this.lastZoomLabel =
                    xaxis && xaxis.min && xaxis.max
                      ? this.fmt(xaxis.min) + ' → ' + this.fmt(xaxis.max)
                      : 'full range'
                  requestAnimationFrame(function () {
                    this.updateStats(chartCtx)
                  })
                }        beforeResetZoom: () => {
                  this.lastZoomLabel = 'full range'
                },
              },
            },
            stroke: { curve: 'straight', width: 1 },
            dataLabels: { enabled: false },
            markers: { size: 0 },
            title: {
              text: 'Line chart — 500,000 raw datapoints',
              align: 'left',
            },
            subtitle: {
              text: 'LTTB downsampling enabled — zoom in to re-sample the raw series at higher resolution within the visible window',
              align: 'left',
            },
            xaxis: {
              type: 'datetime',
              labels: { datetimeUTC: false },
            },
            yaxis: {
              labels: {
                formatter: (val) => {
                  return val.toFixed(2)
                },
              },
            },
            tooltip: { x: { format: 'yyyy-MM-dd HH:mm' } },
          }
    requestAnimationFrame(() => {
            if (this.chart.chart?.w && this.chart.chart?.w.globals && this.chart.chart?.w.globals.series) {
              this.updateStats(this.chart)
            } else {
              requestAnimationFrame(poll)
            }
          })
    document.getElementById('rerender').addEventListener('click', this.rebuild)
    document.getElementById('toggleReducer').addEventListener('change', this.rebuild)
    document.getElementById('resetZoom').addEventListener('click', () => {
            if (this.chart) this.chart.resetSeries(true, true)
          })
  }

  ngOnDestroy() {
    // no cleanup needed
  }
}
Large Dataset Downsampling - Angular Line Charts | ApexCharts.js | ApexCharts.js