D3js fundamentals Part 4 Scales
Tags: javascript, webdev, d3js, tutorial
Published: 2019-11-22 15:32:14

Last article we learnt about `path` data. 
{% post https://dev.to/saikiran/d3js-fundamentals-part-3-svg-path-1bhh %}
As I wrote in the last article, it is not necessary to learn about the `path` data if you want to learn d3js, you can skip that part as it sometimes become too confusing to pickup the concepts and it just helps you in understanding what goes on in the background when you make a `path`.

If you see in this example, We have used data to match our svg width and height, like we used data 100,100 to start from point 100,100 of the svg but we will never be getting data that can match. Some data may be in floating point , some may be in long int, some in date format etc. Here comes the `Scales` in d3js to solve this problem. D3js have some neat features to play with data. 

Lets see the simplest example

{% codepen https://codepen.io/krngd2/pen/JjjzMBv default-tab=js,result %}

###`d3.scaleLinear()` 
In the above example we converted marks to percentages, simply means we took a range of values and fitted it into 0 to 100 range. This we use to fit our range of data, fit into width or height range of the `svg`. Look at this example

{% codepen https://codepen.io/krngd2/pen/oNNVEyv default-tab=js,result %}

We took a different set of data that wouldn't fit in our svg and then scaled it to fit in.

This is our data 

```
let data = [
       {x:-60,y:1120},
       {x:50,y:400},
       {x:160,y:220},
       {x:190,y:280},
       {x:330,y:360},
       {x:420,y:80},
       {x:560,y:560},
       {x:620,y:120},
       {x:930,y:700},
       {x:1120,y:-60}
     ]
```

In the previous article example we have just passed the data directly to the line generator but in this example our data is very different, so we have to define accessor to the line generator for x and y values like this 

``` 
let lineGenerator = d3.line()
                      .x(d => d.x)
                      .y(d => d.y) 
```
Line generator will loop through the data array to get x and y values as returned by the accessor function `.x(d => d.x).y(d => d.y)` and then generate path data. In order to fit in the data to svg, data needs to scaled accordingly. We have to scale it before it gets passed to the x and y values. 
First we initialize the scale by passing the smallest and largest value to domain and 0 to width or height of the svg to range, when the value gets passed it return the appropriate points on the svg.
Lowest point in our svg is -60 and largest value is 1120 which can be passed to domain and svg width is 500px which can be passed to range.
``` 
let scale = d3.scaleLinear()
                      .domain([-60, 1120])
                      .range([0, 500])
```
and convert data
 
``` 
let lineGenerator = d3.line()
                      .x(d => scale(d.x))
                      .y(d => scale(d.y))
```
We can get min and max values of the given data with the help of `d3.extent(data, accessor)`, it will return an array. To get single minimum or maximum value use `d3.min(data,accessor)` and `d3.max(data,accessor)`. You can know more about the array method in d3js [here d3-array](https://github.com/d3/d3-array)

There are 12 types of scaling in d3js which are classified into 3 types
1. Continuous input and continuous output
   * [`d3.scaleLinear()`](https://github.com/d3/d3-scale#linear-scales)
2. Continuous input and discrete output
   * d3.scaleQuantize()
   * d3.scaleQuantile()
   * d3.scaleThreshold()
3. Discrete input and discrete output
   * d3.scaleOrdinal()
   * d3.scaleBand()
   * d3.scalePoint()

You can learn about them [here d3-scale](https://github.com/d3/d3-scale)