Skip to main content

Scales & Domains

Essential scale functions for mapping data values to visual properties.

Linear Scale

Basic Linear Scale

const xScale = d3
.scaleLinear()
.domain([0, 100]) // Input domain
.range([0, 500]); // Output range

console.log(xScale(50)); // 250
console.log(xScale(25)); // 125

Scale with Data

const data = [10, 50, 30, 80, 45];

const yScale = d3
.scaleLinear()
.domain(d3.extent(data)) // [10, 80]
.range([height, 0]); // Invert for SVG coordinates

// Or specify domain manually
const yScale2 = d3
.scaleLinear()
.domain([0, d3.max(data)])
.range([height, 0]);

Scale Methods

const scale = d3.scaleLinear().domain([0, 100]).range([0, 500]);

// Get scaled value
scale(50); // 250

// Invert (get domain value from range)
scale.invert(250); // 50

// Get nice domain
scale.nice(); // Rounds domain to nice values

// Clamp values to range
scale.clamp(true);
console.log(scale(150)); // 500 (clamped)

Band Scale (Categorical Data)

Basic Band Scale

const categories = ['A', 'B', 'C', 'D'];

const xScale = d3.scaleBand().domain(categories).range([0, 400]).padding(0.1);

console.log(xScale('B')); // Position of category B
console.log(xScale.bandwidth()); // Width of each band
console.log(xScale.step()); // Distance between band starts

Band Scale with Padding

const xScale = d3
.scaleBand()
.domain(categories)
.range([0, 400])
.padding(0.1) // Outer padding
.paddingInner(0.1) // Inner padding only
.paddingOuter(0.2); // Outer padding only

Ordinal Scale

Basic Ordinal Scale

const colorScale = d3
.scaleOrdinal()
.domain(['A', 'B', 'C'])
.range(['red', 'blue', 'green']);

console.log(colorScale('A')); // "red"
console.log(colorScale('B')); // "blue"

Built-in Color Schemes

// Category colors
const colorScale = d3.scaleOrdinal(d3.schemeCategory10);
const darkColors = d3.scaleOrdinal(d3.schemeDark2);

// Set domain explicitly
colorScale.domain(['Apple', 'Orange', 'Banana']);

Time Scale

Basic Time Scale

const timeScale = d3
.scaleTime()
.domain([new Date(2020, 0, 1), new Date(2021, 0, 1)])
.range([0, 500]);

// Parse date strings first
const parseDate = d3.timeParse('%Y-%m-%d');
const dates = ['2020-01-01', '2020-06-01', '2020-12-31'];
const parsedDates = dates.map(parseDate);

const timeScale2 = d3
.scaleTime()
.domain(d3.extent(parsedDates))
.range([0, width]);

Time Scale with Nice Ticks

const timeScale = d3
.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([0, width])
.nice(); // Round to nice time intervals

Color Scales

Sequential Color Scale

const colorScale = d3.scaleSequential(d3.interpolateBlues).domain([0, 100]);

console.log(colorScale(25)); // Light blue
console.log(colorScale(75)); // Dark blue

Diverging Color Scale

const colorScale = d3
.scaleDiverging(d3.interpolateRdYlBu)
.domain([-100, 0, 100]); // Negative, neutral, positive

Threshold Scale

const colorScale = d3
.scaleThreshold()
.domain([10, 20, 30])
.range(['red', 'orange', 'yellow', 'green']);

console.log(colorScale(5)); // "red"
console.log(colorScale(15)); // "orange"
console.log(colorScale(25)); // "yellow"
console.log(colorScale(35)); // "green"

Quantile and Quantize Scales

Quantile Scale

const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const quantileScale = d3
.scaleQuantile()
.domain(data)
.range(['low', 'medium', 'high']);

console.log(quantileScale.quantiles()); // [3.67, 6.33]

Quantize Scale

const quantizeScale = d3
.scaleQuantize()
.domain([0, 100])
.range(['low', 'medium', 'high']);

console.log(quantizeScale(25)); // "low"
console.log(quantizeScale(50)); // "medium"
console.log(quantizeScale(75)); // "high"

Log and Power Scales

Log Scale

const logScale = d3.scaleLog().domain([1, 1000]).range([0, 500]).base(10); // Default is e, can specify base

Power Scale

const powerScale = d3.scalePow().domain([0, 100]).range([0, 500]).exponent(2); // Square scale

// Square root scale (shorthand)
const sqrtScale = d3.scaleSqrt().domain([0, 100]).range([0, 500]);

Scale Utilities

Creating Scales from Data

const data = [
{ x: 10, y: 20, category: 'A' },
{ x: 30, y: 40, category: 'B' },
{ x: 50, y: 60, category: 'C' },
];

// Scales from data extents
const xScale = d3
.scaleLinear()
.domain(d3.extent(data, d => d.x))
.range([0, width]);

const yScale = d3
.scaleLinear()
.domain(d3.extent(data, d => d.y))
.range([height, 0]);

const colorScale = d3
.scaleOrdinal(d3.schemeCategory10)
.domain([...new Set(data.map(d => d.category))]);

Scale Composition

// Combine scales for complex mappings
const radiusScale = d3
.scaleSqrt()
.domain([0, d3.max(data, d => d.value)])
.range([5, 30]);

const opacityScale = d3
.scaleLinear()
.domain(d3.extent(data, d => d.confidence))
.range([0.3, 1.0]);

Common Patterns

Margin Convention with Scales

const margin = { top: 20, right: 20, bottom: 30, left: 50 };
const width = 960 - margin.left - margin.right;
const height = 500 - margin.top - margin.bottom;

const xScale = d3
.scaleLinear()
.domain(d3.extent(data, d => d.x))
.range([0, width]); // Use inner width

const yScale = d3
.scaleLinear()
.domain(d3.extent(data, d => d.y))
.range([height, 0]); // Use inner height