Adding Gradient to Shapes in Angular 4 D3 Charts - Netwoven

Adding Gradient to Shapes in Angular 4 D3 Charts

By Debopoma Chaudhury  •  March 27, 2018  •  4561 Views

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 Angular 4 D3 Charts

Leave a comment

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

Dublin Chamber of Commerce
Microsoft Partner
Microsoft Partner
Microsoft Partner
Microsoft Partner
Microsoft Partner
Microsoft Partner
Microsoft Fast Track
Microsoft Partner
Microsoft Fabric
MISA
MISA
Unravel The Complex
Stay Connected

Subscribe and receive the latest insights

Netwoven Inc. - Microsoft Solutions Partner

Get involved by tagging Netwoven experiences using our official hashtag #UnravelTheComplex