Scales are functions that "map a dimension of abstract data to a visual representation". This can be anything from screen coordinates, to circles radii, to colors.
Github: d3-scale
Let's try it with a simple example: code/d3-scales/01_write_a_scale.html.
Scales map an input from a domain to an output range.
Murray: Interactive Data Visualization for the Web
d3 solution to 01_write_a_scale.html:
var myScale = d3.scaleLinear()
.domain([0, 60])
.range([0, 200]);
Linear scales (d3.scaleLinear()
) map an input linearly to an output range:
d3.scaleLinear().domain([20, 100]).range([50, 500]);
// ... gets the same results as:
var scale = function(d){ return
((d - 20) / (100 - 20)) * (500 - 50) + 50;
}
Linear scales do not automatically cut off input values outside of the domain:
var scale = d3.scaleLinear()
.domain([20, 100])
.range([50, 500]);
scale(0); // => -62.5
scale(200); // => 1062.5
Use clamp()
to enforce cut-offs:
var scale = d3.scaleLinear()
.domain([20, 100])
.range([50, 500])
.clamp();
scale(0); // => 50
scale(200); // => 500
d3 linear scales even work with color ranges:
var scale = d3.scaleLinear()
.domain([20, 100])
.range(["aqua", "firebrick"]);
scale(40); // => "rgb(45, 200, 200)"
scale(80); // => "rgb(134, 89, 89)"
All scales support invert()
, which returns the corresponding input for a given output value:
var scale = d3.scaleLinear()
.domain([20, 100])
.range([50, 500]);
scale.invert(500); // => 100
scale.invert(50); // => 20
d3 comes with more built-in continuous scales:
d3.scalePow
for power scales (set exponent with .exponent()
)
d3.scaleSqrt
for a square root scale
d3.scaleLog
for a logarithmic scale
Let's plot these scales... (code/d3-scales/02_continuous.html)
One commonly used input domain is time. d3.scaleTime()
works as a linear scale for that domain.
var s = d3.scaleTime()
.domain([new Date(2017, 0, 1), new Date(2017, 11, 32)])
.range([0, 800]);
s(new Date(2017, 2, 1)) // => 129.31506849315068
s(new Date(2017, 7, 10)) // => 484.2922374429223
d3.scaleOrdinal()
takes an array of ordinal values as its input domain:
var s = d3.scaleOrdinal()
.domain(["apples", "bananas", "oranges"])
.range([0, 300]);
s("apples"); // => 0
s("bananas"); // => 150
s("batman"); // => 300