How to used D3 in Ionic 3

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 ionic-d3js tabs
	npm install d3 --save
	npm install @types/d3 --save-dev --save-exact

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 Tabs Template

We don’t need to test this app on real device, we can test on the browser. First, we modify the existing code of the tab.html. Replace existing code with the following code in pages/tabs/tabs.html

<super-tabs height="100%">
    <super-tab [tabRoot]="tab1Root" title="Bar Chart"></super-tab>
    <super-tab [tabRoot]="tab2Root" title="Pie Chart"></super-tab>
</super-tabs>

Here we are using SuperTabsModule of ionic 2 and we have to import this module in app/app.module.its file. In the app/app.module.ts we also have to import BarChartPage and PieChartPage. Add the following code in app/app.module.ts file

import { NgModule, ErrorHandler } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';

import { BarChartPage } from '../pages/bar-chart/bar-chart';
import { PieChartPage } from '../pages/pie-chart/pie-chart';
import { TabsPage } from '../pages/tabs/tabs';
import { SuperTabsModule } from 'ionic2-super-tabs';

import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

@NgModule({
  declarations: [
    MyApp,
    BarChartPage,
    PieChartPage,
    TabsPage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp),
    SuperTabsModule
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    BarChartPage,
    PieChartPage,
    TabsPage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

 

Modify the pages/tabs/tabs with following code.

import { Component } from '@angular/core';
import { BarChartPage } from '../bar-chart/bar-chart';
import { PieChartPage } from '../pie-chart/pie-chart';

@Component({
  templateUrl: 'tabs.html'
})
export class TabsPage {
  tab1Root = BarChartPage;
  tab2Root = PieChartPage;

  constructor() {}
}

 

Step 3: 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 in 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 pages/bar-chart/bar-chart.html file

<ion-header>
  <ion-navbar>
    <ion-title>{{title}}</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <div id="barChart"></div>
  <!--<svg width="960" height="500"></svg>-->

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

 

Modify the pages/pie-chart/pie-chart.html file 

<ion-header>
  <ion-navbar>
    <ion-title>{{title}}</ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
  <div id="pieChart"></div>
  <!--<svg width="960" height="500"></svg>-->

  <h5 text-center>Election Result of India 2017</h5>
</ion-content>



Step 4: Creating chart

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 src/pages/bar-chart/bar-chart.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import  { StatsBarChart } from '../../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: 'page-bar-chart',
  templateUrl: 'bar-chart.html'
})
export class BarChartPage {

  title = 'D3 Barchart with Ionic 3';

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

  x: any;
  y: any;
  svg: any;
  g: any;

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

  ionViewDidLoad() {
    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 bar chart in ionic.

 

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

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

import  { StatsPieChart } from '../../data/data'

import * as d3 from 'd3-selection';
import * as d3Scale from "d3-scale";
import * as d3Shape from "d3-shape";

@Component({
  selector: 'page-pie-chart',
  templateUrl: 'pie-chart.html'
})
export class PieChartPage {

  title: string = 'D3 Pie Chart in Ionic 3';

  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(public navCtrl: NavController) {
    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;
  }

  ionViewDidLoad() {
    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() {
    let 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.