Create high perfomance custom graphs and charts in Angular

How to create performant custom charts and graphs with d3 and ngx-chart

Anna Melashkina
medialesson
4 min readJul 9, 2020

--

Introduction

Recently my colleagues and me were developing a solution for an IoT company. This company had a lot of different devices, that were sending a huge amount of data from their sensors. Our goal was to show these indicators in a web view. We chose angular as a framework for the client-side with the ngx-charts library.

First, ngx-charts was suitable for our requests. In fact, it’s a great tool for data visualization. But at some point, when we started getting more and more data from the sensors, we were running into huge performance issues. One chart that had 100.000+ points took over 1 minute to be presented to the user. On top of that, the customer wanted to have some unique graphs (e.g. a graph that shows not only values but also tolerance). So, we started searching for ideas on how we can do this.

Since ngx-charts uses d3 under the hood, we thought it might be a good idea to use it directly for our needs. We created a custom chart with d3 on canvas and used ngx-charts as an emulator for axes because we wanted to be consistent with other charts in our project.

Today I want to show you how we implemented a custom graph with d3 and emulated coordinate axes with ngx-charts.

Step 1: Init app

As any other project let’s start with the setup.

  1. Install angular cli.
  2. Create a new angular app ng new angular-custom-graph. We’re not going to use routes, so select “n” and choose scss.
  3. Remove the sample code in app.component.html.
  4. Install packages:

cd .\angular-custom-graph\

npm i @swimlane/ngx-charts — save

npm i @angular/cdk — save

npm i @angular/animations — save

npm i d3 — save

npm i @types/d3 — save-dev

5. Add NgxChartsModule and BrowserAnimationsModule to app.module.ts.

Step 2: Component preparation

Create a graph component ng g component ScatterLineChart. This is going to be our custom chart. Let’s extend BaseChartComponent by changing the scatter-line-chart.component.ts as following:

Add following code to app.component.scss:

and app.component.html:

Step 3: Sample data generation

For the graph, we need some sample data. Let’s create a model for this and a service, that will provide the data.

  1. Generate service: ng g s DataProvider.
  2. Create file shot-data.ts next to data-provider.service.ts and paste the following code:

3. Generate data in data provider (data-provider.service.ts):

4. For this demo inject the service to the AppComponent and log the chart data in the console to see if it works. It should generate 100.000 random points:

Step 4: Graph configuration

In this section are going to create a chart configuration and provide it to ScatterLineChart.

  1. Create file scatter-line-series.model.ts in scatter-line-chart folder and paste the following code:

2. Implement GraphColorManager and GraphConfig in shot-data.ts:

3. Provide config to ScatterLineChart. Create config instance in AppComponent:

To provide the data and the chartConfig to the chart component add [results]=”data” [config]=”chartConfig” to app.component.html:

Also, you will need to add @Input() config: ChartConfig<T>; to scatter-line-chart.component.ts

After all these manipulations your chart will get configurable for the data selector, color selector, and data itself.

Step 5: Draw points

After we got data in the chart, let’s draw it. For this step, we will need to create canvas, painters, and calculate view dimensions.

  1. Let’s create painters, they will draw points on the canvas. Create two files circle.painter.ts and scatter-series.painter.ts and paste the code below:

2. Next, we need to calculate the scales based on the incoming data and view dimensions. Update your scatter-line-chart.component.ts to this:

3. Finally, add canvas to scatter-line-chart.component.html:

Voila! If you were following this tutorial you should get the next chart:

Visualized 10000 random points

You can change the number of points in the data provider service to 20. You’ll see something like this:

Visualized 20 random points

Step 6: add the coordinate system

  1. The final step is to add a coordinate system. Everything we have to do is to add ngx-charts-chart to scatter-line-chart.component.html, because all calculations are already done. scatter-line-chart.component.html will look like this:

2. As for now, the coordinate system is added, but it’s not aligned with the graph. Let’s add some css to fix it. Change scatter-line-chart.component.scss as following:

Result and conclusion:

Final result (600 points)

In the end, we get the this custom chart, where the blue points show tolerance and the colored points show custom data. This graph is performant and can handle a huge number of points. We are using d3 to calculate point coordinates and render them on canvas. ngx-charts provide us the coordinate system.

We are still using ngx-charts library for other graph renderings, but when it comes to huge amounts of data it’s better to implement custom rendering. Although it raises other questions like how to show a legend or tooltips, but this is another topic, which can be told in another article.

The full example can be found here: https://github.com/aosyatnik/angular-custom-graph

--

--