Edupala

Comprehensive Full Stack Development Tutorial: Learn Ionic, Angular, React, React Native, and Node.js with JavaScript

D3 Bar Chart

When we are making a bar chart, we need scaleBand() function to create a band for each domain in a bar chart. In the above bar chart picture, we had use scaleBand() on the x-axis to create separate rectangle or band for each salesman.  Here we have used discrete domain value as salesman name as domain input and we used the continuous value from zero to width for range value. The scaleBand will calculate inner padding and outer padding for our band on a bar chart.

In D3 version 4, some of the function had replaced as

  1. v4’s .scaleBand() replaced v3’s .scale.ordinal().
  2. v4’s .rangeRound() and .padding() replaced v3’s rangeRoundBands().

scaleBand function: 
Band scales are like ordinal scales except the output range is continuous and numeric. The scaleBand have a discrete domain and will generate the range of continue value or uniform bands for each domain. Band scales are typically used for bar charts with an ordinal or categorical dimension.
When creating bar charts scaleBand helps to determine the geometry of the bars, taking into account padding between each bar. The domain is specified as an array of values or the discrete value  (one value for each band) and the range as the minimum and maximum extents of the bands plus padding (e.g. the total width of the bar chart).

Case 1: scaleBand without domain value.
x = d3.scaleBand() .range([0, width]);
Constructs a new band scale with the empty domain, the unit range [0, 1], no padding, no rounding and center alignment. We can assign the domain later by calling

x.domain(data.map(function(d) { return d.salesperson; }));

Case 2: scaleBand without domain value.

var bandScale = d3.scaleBand()
  .domain(['Mon', 'Tue', 'Wed', 'Thu', 'Fri'])
  .range([0, 200]);

bandScale('Mon'); // returns 0
bandScale('Tue'); // returns 40
bandScale('Fri'); // returns 160

Here scaleBand will split the range into n bands (where n is the number of values in the domain array) and compute the positions and widths of the bands taking into account any specified padding.

The width of each band can be accessed using .bandwidth():
bandScale.bandwidth(); // returns 40

Two types of padding may be configured:

  • The paddingInner which specifies (as a percentage of the bandwidth) the amount of padding between each band
  • The paddingOuter which specifies (as a percentage of the bandwidth) the amount of padding before the first band and after the last band

bandScale.paddingInner(0.05);

d3.scaleLinear():
The mapping performed is linear in that the output range is calculated using a linear function of the input domain.
Linear scales are a good default choice for continuous quantitative data because they preserve proportional differences. Each range value y can be expressed as a function of the domain value
x: y = mx + b.

Here we will create simple bar chart

Add the following code in index.html

<style>
.bar { fill: steelblue; }<br />
</style>
<!-- load the d3.js library --> 
<script src="//d3js.org/d3.v4.min.js"></script> 
<script>
// set the dimensions and margins of the graph
var margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = 760 - margin.left - margin.right,
    height = 400 - margin.top - margin.bottom;

// set the ranges
var x = d3.scaleBand()
          .range([0, width])
          .padding(0.1);
    
var y = d3.scaleLinear()
          .range([height, 0]);
          
// append the svg object to the body of the page
// append a 'group' element to 'svg'
// moves the 'group' element to the top left margin

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", 
          "translate(" + margin.left + "," + margin.top + ")");

// get the data
d3.csv("sales.csv", function(error, data) {
  if (error) throw error;

  // format the data
  
  data.forEach(function(d) {     
    d.sales = +d.sales;
  });

  // Scale the range of the data in the domains
  
  x.domain(data.map(function(d) { return d.salesperson; }));
  y.domain([0, d3.max(data, function(d) { return d.sales; })]);

  
  // append the rectangles for the bar chart
  
  svg.selectAll(".bar")
      .data(data)
    .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x(d.salesperson); })
      .attr("width", x.bandwidth())
      .attr("y", function(d) { return y(d.sales); })
      .attr("height", function(d) { return height - y(d.sales); });

	  
  // add the x Axis
  
  svg.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

	  
  // add the y Axis
  
  svg.append("g")
      .call(d3.axisLeft(y));

});
</script>

Add following code in sales.csv

salesperson,sales
Sharma,33
Raj,12
Ajay,41
Arjun,16
Shihab,59
Royan,38
Max,21
Tenzin,25
Kumar,30
Lisa,47
Tom,5
Jerry,20
John,13
Tamo,29

Note: Important code in above code example

1.  Finding SVG element position in our page.

Here the translate will find the x and y position of svg element in our page and will assign x=40 and y=2 as we already assign
margin.left as 40 and margin.right as 20
var svg = d3.select("body").append("svg") ...
  .append("g")
    .attr("transform", 
          "translate(" + margin.left + "," + margin.top + ")"); 

2. We are making a band or rectangle for each domain. As for rectangle in SVG, we have 4 values required as x,y position, width, and height.

D3 Bar Chart

Leave a Reply

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

Scroll to top