How to used D3 in Ionic 4 or Angular

The D3 has become a standard for data visualization. We have a lot of libraries for adding charts in Ionic. We can use Chart.js and angular2-highcharts. The Chart.js is easy to use and allow us to build chart quickly as compared to D3. The D3 has a more learning curve as compared to other chart libraries. The D3 allows us to create more complex and provide more flexibility in creating data visualization on the web.

In this example, we will test simple example how to integrate D3 chart in Ionic 3. Follow the following step

Step 1: Create and  configure the D3 Ionic apps

	ionic start d3js blank
	npm install d3 --save

With D3 version 4 is a collection of the modules and we can use each module independently, with minimum dependency. In this example, we are using the D3 whole module.

Add two more page to our apps

ionic generate page bar-chart
ionic generate page pie-chart

Step 2: Set up the Char Template

The D3 uses an SVG element of HTML to display graphic on the web. We will be creating two different charts on two pages. First, we need to set up the data on which D3 is generating the chart. Create a new folder called data and add data.ts a file in the data folder. Add the following data in src/data/data.ts file

export const StatsPieChart: any[] = [
    {party: 'BJP', electionP: 56},
    {party: 'INC', electionP: 18},
    {party: 'AA', electionP: 10},
    {party: 'CPI', electionP: 5},
    {party: 'CPI-M', electionP: 5},
    {party: 'BSP', electionP: 7},
    {party: 'AITS',  electionP: 10}
];

export interface Employee {
    company: string;
    frequency: number;
}

export const StatsBarChart: Employee[] = [
    {company: 'Apple', frequency: 100000},
    {company: 'IBM', frequency: 80000},
    {company: 'HP', frequency: 20000},
    {company: 'Facebook', frequency: 70000},
    {company: 'TCS', frequency: 12000},
    {company: 'Google', frequency: 110000},
    {company: 'Wipro', frequency: 5000},
    {company: 'EMC', frequency: 4000}
];

Modify the app/bar-chart/bar-chart.page.html file

<ion-header>
  <ion-toolbar>
    <ion-title>{{ title }}</ion-title>
    <ion-buttons slot="end">
      <ion-button color="primary" routerLink="/pie-chart">Pie Chart
      </ion-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

<ion-content>
  <h2>Bar Chart</h2>
  <div id="barChart"></div>

  <h5 text-center>Employee Statistic of Diff Company</h5>
</ion-content>

Modify the app/pie-chart/pie-chart.page.html file 

<ion-header>
  <ion-toolbar>
    <ion-title>{{ title }}</ion-title>
    <ion-buttons slot="end">
      <ion-button color="primary" routerLink="/bar-chart">Pie Chart
      </ion-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

<ion-content>
  <div id="pieChart"></div>
  <h5 text-center>Election Result of India 2019</h5>
</ion-content>



Step 4: Creating chart in our app

Now we will generate the two chart, first, we will generate a bar chart. In the bar chart, we generate bar chart on the number of employees in popular IT company. This is just fake data, as for example, we are using it.

Modify the following code in app/bar-chart/bar-chart.page.ts

import { Component, OnInit } from '@angular/core';
import { StatsBarChart } from '../../assets/data/data';

import * as d3 from 'd3-selection';
import * as d3Scale from 'd3-scale';
import * as d3Array from 'd3-array';
import * as d3Axis from 'd3-axis';


@Component({
  selector: 'app-bar-chart',
  templateUrl: './bar-chart.page.html',
  styleUrls: ['./bar-chart.page.scss'],
})
export class BarChartPage implements OnInit {

  title = 'D3 Barchart with Ionic 4';
  width: number;
  height: number;
  margin = { top: 20, right: 20, bottom: 30, left: 40 };
  x: any;
  y: any;
  svg: any;
  g: any;

  constructor() {
    this.width = 900 - this.margin.left - this.margin.right;
    this.height = 500 - this.margin.top - this.margin.bottom;
  }

  ngOnInit() {
    this.initSvg();
    this.initAxis();
    this.drawAxis();
    this.drawBars();
  }

  initSvg() {
    this.svg = d3.select('#barChart')
      .append('svg')
      .attr('width', '100%')
      .attr('height', '100%')
      .attr('viewBox', '0 0 900 500');
    this.g = this.svg.append('g')
      .attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');
  }

  initAxis() {
    this.x = d3Scale.scaleBand().rangeRound([0, this.width]).padding(0.1);
    this.y = d3Scale.scaleLinear().rangeRound([this.height, 0]);
    this.x.domain(StatsBarChart.map((d) => d.company));
    this.y.domain([0, d3Array.max(StatsBarChart, (d) => d.frequency)]);
  }

  drawAxis() {
    this.g.append('g')
      .attr('class', 'axis axis--x')
      .attr('transform', 'translate(0,' + this.height + ')')
      .call(d3Axis.axisBottom(this.x));
    this.g.append('g')
      .attr('class', 'axis axis--y')
      .call(d3Axis.axisLeft(this.y))
      .append('text')
      .attr('class', 'axis-title')
      .attr('transform', 'rotate(-90)')
      .attr('y', 6)
      .attr('dy', '0.71em')
      .attr('text-anchor', 'end')
      .text('Frequency');
  }

  drawBars() {
    this.g.selectAll('.bar')
      .data(StatsBarChart)
      .enter().append('rect')
      .attr('class', 'bar')
      .attr('x', (d) => this.x(d.company))
      .attr('y', (d) => this.y(d.frequency))
      .attr('width', this.x.bandwidth())
      .attr('height', (d) => this.height - this.y(d.frequency));
  }

}

As we know that D3 is collections of modules,  we are importing some of the different module needed to generate a bar chart in ionic.

Modify the following code in src/pages/pie-chart/pie-chart.page.ts

import { Component, OnInit } from '@angular/core';
import { StatsPieChart } from '../../assets/data/data';
import * as d3 from 'd3-selection';
import * as d3Scale from 'd3-scale';
import * as d3Shape from 'd3-shape';

@Component({
  selector: 'app-pie-chart',
  templateUrl: './pie-chart.page.html',
  styleUrls: ['./pie-chart.page.scss'],
})
export class PieChartPage implements OnInit {

  title = 'D3 Pie Chart in Ionic 4';

  margin = {top: 20, right: 20, bottom: 30, left: 50};
  width: number;
  height: number;
  radius: number;

  arc: any;
  labelArc: any;
  labelPer: any;
  pie: any;
  color: any;
  svg: any;

  constructor() {
    this.width = 900 - this.margin.left - this.margin.right ;
    this.height = 500 - this.margin.top - this.margin.bottom;
    this.radius = Math.min(this.width, this.height) / 2;
  }

  ngOnInit() {
    this.initSvg();
    this.drawPie();
  }

  initSvg() {
    this.color = d3Scale.scaleOrdinal()
        .range(['#FFA500', '#00FF00', '#FF0000', '#6b486b', '#FF00FF', '#d0743c', '#00FA9A']);
    this.arc = d3Shape.arc()
        .outerRadius(this.radius - 10)
        .innerRadius(0);
    this.labelArc = d3Shape.arc()
        .outerRadius(this.radius - 40)
        .innerRadius(this.radius - 40);

    this.labelPer = d3Shape.arc()
        .outerRadius(this.radius - 80)
        .innerRadius(this.radius - 80);

    this.pie = d3Shape.pie()
        .sort(null)
        .value((d: any) => d.electionP);

    this.svg = d3.select('#pieChart')
        .append('svg')
        .attr('width', '100%')
        .attr('height', '100%')
        .attr('viewBox', '0 0 ' + Math.min(this.width, this.height) + ' ' + Math.min(this.width, this.height))
        .append('g')
        .attr('transform', 'translate(' + Math.min(this.width, this.height) / 2 + ',' + Math.min(this.width, this.height) / 2 + ')');
  }

  drawPie() {
    const g = this.svg.selectAll('.arc')
        .data(this.pie(StatsPieChart))
        .enter().append('g')
        .attr('class', 'arc');
    g.append('path').attr('d', this.arc)
        .style('fill', (d: any) => this.color(d.data.party) );
    g.append('text').attr('transform', (d: any) => 'translate(' + this.labelArc.centroid(d) + ')')
        .attr('dy', '.35em')
        .text((d: any) => d.data.party);

    g.append('text').attr('transform', (d: any) => 'translate(' + this.labelPer.centroid(d) + ')')
        .attr('dy', '.35em')
        .text((d: any) => d.data.electionP + '%');
  }

}

We can modify the data to change to generate different pie and bar chart and we can use same method to generate different graphic of D3 in ionic.