Scales are functions that map data values (the domain) to pixel positions (the range). Below, the hand-rolled linearScale() from Module 02 runs side-by-side with D3's scaleLinear(). They produce identical output — D3 just gives you more features.
They are the same math. D3's scaleLinear() is doing the exact same fraction-based interpolation as the manual function. But D3 adds .nice(), .ticks(), .invert(), and .clamp() on top.
2. d3.scaleBand() for Categorical Data
Unlike scaleLinear(), which maps numbers to numbers, scaleBand() maps categories (strings) to evenly-spaced bands. Each band has a starting position and a width. This is what you need for the x-axis of a bar chart.
This is the key insight: a D3 scale is a plain JavaScript function. You call it with a value and get a pixel back. There is no magic.
// Create the scale
const yScale = d3.scaleLinear()
.domain([0, 1250])
.range([300, 0]);
// It's just a function:
typeof yScale; // "function"
yScale(1250); // 0 (max value → top)
yScale(0); // 300 (min value → bottom)
yScale(625); // 150 (midpoint → middle)
// Use it anywhere you'd use a function:
data.map(d => yScale(d.views)); // → array of pixel positions
svg.selectAll('rect')
.attr('y', d => yScale(d.views)); // D3 calls the function per element
Bonus features that come free: yScale.invert(150) → 625 (pixel back to data value — useful for mouse position decoding) yScale.ticks(5) → [0, 250, 500, 750, 1000, 1250] (nice tick values for axes) yScale.nice() → rounds domain to friendly boundaries