2851 Views
6 minutes read
Categories
AngularJS

Adding Gradient to Shapes in Angular 4 D3 Charts

Many a time in D3 charts there might be a requirement to add gradient inside shapes (like circles /squares /rectangles). In that case, one needs to add a linear gradient to the charts and use it to dynamically fill the shapes. In this example, I will show how to achieve this in circles.

Method of adding gradient to D3 shapes in charts:

Create a sample Angular 4 App:

  • To create a sample application first open console in a system which has node.js, npm and angular-cli installed.
  • In the console go to a folder (say Project) and inside it, write the following command:
ng new circle-grad
  • This would create a folder circle-grad with all necessary angular files contained in it.
  • To run this sample application, go to console and type the following commands:
cd circle-grad
ng serve –o
  • This will open the sample angular application in the default browser at port 4200(default port)

Install D3 to the sample App:

  • In console go to circle-grad folder and type the below commands to install D3:
npm install –save d3
npm install –save -dev @types/d3

Create child components in the sample App:

I created two child components to depict vertical and horizontal gradient in the charts.

  • To create child components, go to circle-grad folder in console and type the following commands:
ng g component shared/circlex
ng g component shared/circley

Add svg to the sample App:

  • Add svg and child component references as shown in the sample application:
    app.component.html
<div id="graph-panel-wrapper">
  <div id="graph-container" style="position:relative;">
      <svg width="100%" height="100%" style="overflow: hidden;">
          <g app-circle-x id="circleX"></g>
          <g app-circle-y id="circleY"></g>
      </svg>    
  </div>
</div>

Setup child components:

  • First, we need to add d3 reference.
  • Then we need to mention the child selector referenced in app.component. html as shown:
    circle-x.component.ts
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import * as d3 from 'd3';
@Component({
  selector: '[app-circle-x]',
  templateUrl: './circle.component.html',
  styleUrls: ['./circle.component.css'],
  encapsulation: ViewEncapsulation.None
})
export class CircleXComponent implements OnInit {
  private chartX: any;
  constructor() { }

  ngOnInit() {
}
}
  • Same thing should be done in circle-y.component.html

Creating graph with gradient circles in child components:

  • Inside ngOnInit() we need to write our code for generating the D3 graph
  • First, we create some dummy arrays for dummy data. This data can be dynamic based on your requirements.
    circle-x.component.ts
let dumArray = [{ x: 100, y: 100 }, { x: 200, y: 100 }, { x: 300, y: 100 }, { x: 400, y: 100 }, { x: 400, y: 100 }, { x: 500, y: 100 }, { x: 600, y: 100 }, { x: 700, y: 100 }];
let gradData = [{ x: 100, grad: 0 }, { x: 200, grad: 25 }, { x: 300, grad: 33 }, { x: 400, grad: 50 }, { x: 500, grad: 75 }, { x: 600, grad: 88 }, { x: 700, grad: 100 }];    

circle-y.component.ts

let dumArray = [{ x: 100, y: 200 }, { x: 200, y: 200 }, { x: 300, y: 200 }, { x: 400, y: 200 }, { x: 400, y: 200 }, { x: 500, y: 200 }, { x: 600, y: 200 }, { x: 700, y: 200 }];
let gradData = [{ x: 100, grad: 100 }, { x: 200, grad: 88 }, { x: 300, grad: 75}, { x: 400, grad: 50 }, { x: 500, grad: 33 }, { x: 600, grad: 25 }, { x: 700, grad: 0 }];
  • The first array depicts the x-y co-ordinates for the circles in the graph.
  • The second array depicts the x co-ordinate position of the circles and the gradient values for each circle.
  • Next, we need to define the scale so the we can position multiple graphs inside the parent svg as shown:
    circle-x.component.ts
let maxValue = Math.max.apply(Math, dumArray.map(function (item) { return item.y; }));
let minValue = Math.min.apply(Math, dumArray.map(function (item) { return item.y; }))
let scale = d3.scaleLinear()
      .domain([minValue, maxValue])
      .range([35, 25]);

circle-y.component.ts

let maxValue = Math.max.apply(Math, dumArray.map(function (item) { return item.y; }));
let minValue = Math.min.apply(Math, dumArray.map(function (item) { return item.y; }))
let scale = d3.scaleLinear()
      .domain([minValue, maxValue])
      .range([85, 75]);
  • Next, we need to select the container for the graph
    circle-x.component.ts
this.chartX= d3.select("#circleX")

circle-y.component.ts

this.chartY= d3.select("#circleY")
  • Next, we need to create the linear gradients as shown below:
    circle-x.component.ts
let gradX = this.chartX
      .append("defs").selectAll("linearGradient").data(gradData).enter()
      .append("linearGradient")
      .attr("id", function (d) { return "gradX" + d.x})
      .attr("x1", "0%")
      .attr("x2", "0%")
      .attr("y1", "100%")
      .attr("y2", "0%")
      gradX.append("stop")
      .attr("offset", function (d) { return d.grad + "%" })
      .attr("stop-color", function (d) { return "red"; })
      gradX.append("stop")
      .attr("offset", function (d) { return (d.grad) + "%" })
      .attr("stop-color", "white");

The highlighted lines indicate horizontal gradient.
circle-y.component.ts

let gradY = this.chartY
    .append("defs").selectAll("linearGradient").data(gradData).enter()
    .append("linearGradient")
    .attr("id", function (d) { return "gradY" + d.x})
    .attr("x1", "100%")
    .attr("x2", "0%")
    .attr("y1", "0%")
    .attr("y2", "0%")
    gradY.append("stop")
    .attr("offset", function (d) { return d.grad + "%" })
    .attr("stop-color", function (d) { return "blue"; })
    gradY.append("stop")
    .attr("offset", function (d) { return (d.grad) + "%" })
    .attr("stop-color", "white");

The highlighted lines indicate vertical gradient.

  • Next, we need to draw the line and path on which the circles are placed. This step is optional. Based on your requirement you can choose to draw the line /not.
    circle-x.component.ts
let line = d3.line()
      .x(function (d) { return d.x }) 
      .y(function (d) { return scale(d.y) })

    this.chartX.append('path')
      .datum(dumArray)
      .attr('class', 'line')
      .style('fill', 'none')
      .style('stroke', "red")
      .style('stroke-width', '0.5')
      .attr('d', line)

circle-y.component.ts


let line = d3.line<any>()
      .x(function (d) { return d.x }) 
      .y(function (d) { return scale(d.y) })

    this.chartY.append('path')
      .datum(dumArray)
      .attr('class', 'line')
      .style('fill', 'none')
      .style('stroke', "blue")
      .style('stroke-width', '0.5')
      .attr('d', line)
  • Lastly, we plot the circles as per dummy data.
    circle-x.component.ts
this.chartX.selectAll('.dotX')
      .data(dumArray)
      .enter()
      .append('circle')
      .attr('class', 'dotX')
      .attr('cx', d => d.x)
      .attr('cy', d => scale(d.y))
      .attr('r', 15)
      .style("stroke", "red")
      .style("fill", d => {
        let returnColor;
        returnColor = "url(#gradX" + d.x + ")"
        return returnColor;

circle-y.component.ts

this.chartY.selectAll('.dotY')
      .data(dumArray)
      .enter()
      .append('circle')
      .attr('class', 'dotY')
      .attr('cx', d => d.x)
      .attr('cy', d => scale(d.y))
      .attr('r', 15)
      .style("stroke", "blue")
      .style("fill", d => {
        let returnColor;
        returnColor = "url(#gradY" + d.x + ")"
        return returnColor;
      })

The highlighted lines depict reference to the gradients and fill the circles accordingly.

  • The output of this code is displayed below (The application will run in your localhost at port 4200) : (http://localhost:4200/ )
Adding Gradient to Shapes in Angular4 D3 Charts

Debopoma Chaudhury

About Debopoma Chaudhury

Debopoma has around 8+ years of experience in Software Development. She has expertise in Estimation, Analysis, Design, Development and Testing using C#, Ext.JS, Angular JS, Bootstrap, jQuery and SQL. Also, she has exposure on Microsoft technologies using AJAX, Telerik Controls, Web Application in Visual Studio 2008, ASP.Net 4.0, Bryntum Gantt and hold proficiency in Regression Analysis, Agile Methodology, Test Execution and Test Documentation.

Debopoma did her Graduation in B.Tech (Computer Science Engineering ) from St. Thomas College in 2008 and was the Gold Medalist in her University WBUT.

Prior to joining Netwoven, she was working with Infosys and Kovair Pvt. Ltd, Kolkata as Team Lead.

A native of West Bengal, she is presently living in Kolkata with her spouse. During her leisure time, she loves singing, writing short stories and travelling.

LinkedinTwitterFacebook

Leave a Reply

Your email address will not be published. Required fields are marked *