Advanced color scale generation with domain mapping, interpolation modes, and class-based scaling for data visualization applications.
Create color scales for mapping data values to colors with extensive configuration options.
/**
* Create color scale function
* @param colors - Initial colors for the scale (optional)
* @returns Scale instance with configuration methods
*/
function scale(colors?: (Color | string)[]): Scale;
interface Scale {
/** Map scale to numeric domain */
domain(values: number[]): Scale;
/** Set color range */
range(colors: (Color | string)[]): Scale;
/** Set interpolation mode */
mode(mode: string): Scale;
/** Set number of classes or specific breakpoints */
classes(num: number | number[]): Scale;
/** Set output format */
out(format: string): Scale;
/** Set color spread/distribution */
spread(amount: number): Scale;
/** Enable perceptual lightness correction */
correctLightness(enable?: boolean): Scale;
/** Set padding (crop colors from ends) */
padding(pad: number | number[]): Scale;
/** Get array of colors */
colors(count?: number): (Color | string)[];
/** Enable/disable caching */
cache(enable?: boolean): Scale;
/** Set gamma correction */
gamma(value: number): Scale;
/** Set color for no-data values */
nodata(color: Color | string): Scale;
/** Map value to color */
(value: number): Color | string;
}Usage Examples:
import chroma, { scale } from "chroma-js";
// Basic scale from red to blue
const basicScale = scale(['red', 'blue']);
console.log(basicScale(0.5).hex()); // Color at midpoint
// Get discrete colors
const colors = basicScale.colors(5); // Array of 5 colors
// Map to specific domain
const temperatureScale = scale(['blue', 'white', 'red'])
.domain([-10, 0, 40]); // Temperature range
const coldColor = temperatureScale(-5); // Blueish
const neutralColor = temperatureScale(0); // White
const hotColor = temperatureScale(30); // ReddishMap scales to specific numeric domains for data visualization.
/**
* Set domain values for scale mapping
* @param values - Array of domain values (2+ values)
* @returns Scale instance for chaining
*/
domain(values: number[]): Scale;Usage Examples:
// Linear domain
const linearScale = scale(['#000', '#fff']).domain([0, 100]);
console.log(linearScale(25).hex()); // 25% gray
// Multi-point domain
const divergingScale = scale(['red', 'white', 'blue'])
.domain([-100, 0, 100]);
// Asymmetric domain
const skewedScale = scale(['green', 'yellow', 'red'])
.domain([0, 10, 100]); // More resolution in lower range
// Data-driven domain
const data = [1.2, 3.4, 5.6, 12.1, 18.9, 25.3];
const dataScale = scale(['lightblue', 'darkblue'])
.domain([Math.min(...data), Math.max(...data)]);Set the color range for scales with multiple color stops.
/**
* Set color range for the scale
* @param colors - Array of colors defining the range
* @returns Scale instance for chaining
*/
range(colors: (Color | string)[]): Scale;Usage Examples:
// Change range after creation
const myScale = scale().range(['purple', 'green', 'orange']);
// Color brewer palettes
const brewerScale = scale().range(chroma.brewer.Spectral);
// Custom color progression
const customScale = scale().range([
'#440154', // Dark purple
'#31688e', // Blue
'#35b779', // Green
'#fde725' // Yellow
]);
// Warm to cool
const temperatureColors = scale().range([
chroma.temperature(2000), // Warm
chroma.temperature(6500) // Cool
]);Configure how colors are interpolated between scale points.
/**
* Set interpolation mode
* @param mode - Interpolation mode
* @returns Scale instance for chaining
*/
mode(mode: string): Scale;Available modes:
lrgb - Linear RGB (default)rgb - Standard RGBlab - Lab color space (perceptually uniform)lch - LCH color space (good for hue transitions)hsl - HSL color spacehsv - HSV color spacehcg - HCG color spaceoklab - OKLab color space (modern, perceptually uniform)oklch - OKLCH color spaceUsage Examples:
const colors = ['red', 'blue'];
// Different interpolation modes
const rgbScale = scale(colors).mode('rgb');
const labScale = scale(colors).mode('lab');
const lchScale = scale(colors).mode('lch');
const oklabScale = scale(colors).mode('oklab');
// Compare results at midpoint
console.log(rgbScale(0.5).hex()); // RGB interpolation
console.log(labScale(0.5).hex()); // Lab interpolation (better)
console.log(lchScale(0.5).hex()); // LCH interpolation (good for hue)
console.log(oklabScale(0.5).hex()); // OKLab (most modern)
// Best practices
const scientificScale = scale(['blue', 'red']).mode('lab');
const designScale = scale(['blue', 'red']).mode('lch');Create discrete color classes for choropleth maps and categorical data.
/**
* Set number of classes or specific breakpoints
* @param num - Number of classes or array of breakpoints
* @returns Scale instance for chaining
*/
classes(num: number | number[]): Scale;Usage Examples:
// Equal interval classes
const equalScale = scale(['lightblue', 'darkblue'])
.domain([0, 100])
.classes(5);
// Custom breakpoints
const customBreaks = scale(['green', 'yellow', 'red'])
.domain([0, 100])
.classes([0, 25, 50, 75, 90, 100]);
// Get discrete colors
const palette = equalScale.colors(); // Returns 5 colors
// Map values to classes
console.log(equalScale(15).hex()); // Maps to appropriate class
console.log(equalScale(65).hex()); // Different classControl the output format of scale functions.
/**
* Set output format
* @param format - Output format ('hex', 'rgb', 'hsl', etc.)
* @returns Scale instance for chaining
*/
out(format: string): Scale;Usage Examples:
const myScale = scale(['red', 'blue']);
// Different output formats
const hexScale = myScale.out('hex');
console.log(hexScale(0.5)); // "#800080"
const rgbScale = myScale.out('rgb');
console.log(rgbScale(0.5)); // [128, 0, 128]
const cssScale = myScale.out('css');
console.log(cssScale(0.5)); // "rgb(128,0,128)"
// Use in different contexts
const webColors = scale(['#ff0000', '#0000ff']).out('hex').colors(10);
const canvasColors = scale(['#ff0000', '#0000ff']).out('rgb').colors(10);Advanced options for fine-tuning scale behavior.
/**
* Set color spread/distribution
* @param amount - Spread amount (0-1+)
* @returns Scale instance for chaining
*/
spread(amount: number): Scale;
/**
* Enable perceptual lightness correction
* @param enable - Enable correction (default: true)
* @returns Scale instance for chaining
*/
correctLightness(enable?: boolean): Scale;
/**
* Set padding (crop colors from ends)
* @param pad - Padding amount or [start, end] padding
* @returns Scale instance for chaining
*/
padding(pad: number | number[]): Scale;
/**
* Enable/disable caching for performance
* @param enable - Enable caching (default: true)
* @returns Scale instance for chaining
*/
cache(enable?: boolean): Scale;
/**
* Set gamma correction
* @param value - Gamma value (default: 1)
* @returns Scale instance for chaining
*/
gamma(value: number): Scale;
/**
* Set color for no-data/invalid values
* @param color - Color for no-data values
* @returns Scale instance for chaining
*/
nodata(color: Color | string): Scale;Usage Examples:
// Advanced scale configuration
const advancedScale = scale(['red', 'white', 'blue'])
.domain([0, 50, 100])
.mode('lab')
.correctLightness(true) // Better perceptual uniformity
.padding([0.1, 0.1]) // Crop 10% from each end
.gamma(1.2) // Gamma correction
.nodata('#cccccc'); // Gray for invalid data
// Performance optimization
const fastScale = scale(['blue', 'red'])
.cache(true) // Enable caching
.out('hex'); // Pre-set output format
// Color distribution control
const spreadScale = scale(['red', 'blue'])
.spread(0.8); // Adjust color distribution
// Handle missing data
console.log(advancedScale(NaN)); // Returns nodata color
console.log(advancedScale(null)); // Returns nodata colorUse scales with data analysis for optimal color mapping.
// Integration with analyze() function for data-driven scales
function createDataScale(data: number[], colors: (Color | string)[], mode?: string): Scale;Usage Examples:
import chroma, { scale, analyze, limits } from "chroma-js";
// Analyze data for optimal scale
const data = [1.2, 3.4, 5.6, 12.1, 18.9, 25.3, 45.2, 67.8, 89.1];
const analysis = analyze(data);
// Create scale based on data distribution
const dataScale = scale(['lightblue', 'darkblue'])
.domain([analysis.min, analysis.max]);
// Use quantile-based classes
const quantileBreaks = limits(analysis, 'q', 5); // 5 quantile classes
const quantileScale = scale(['green', 'yellow', 'red'])
.domain(quantileBreaks);
// Equal interval classes
const equalBreaks = limits(analysis, 'e', 5); // 5 equal intervals
const equalScale = scale(['blue', 'red'])
.domain(equalBreaks);
// Use with real data
const populationData = [1200, 3400, 5600, 12100, 18900];
const popAnalysis = analyze(populationData);
const populationScale = scale(chroma.brewer.OrRd)
.domain([popAnalysis.min, popAnalysis.max])
.classes(5);
// Map data to colors
const dataColors = populationData.map(value => populationScale(value).hex());Common scale configurations for typical use cases.
// Common scale patterns (not direct API, but common usage patterns)
/**
* Diverging scale (centered on zero)
*/
function createDivergingScale(colors: string[], center?: number): Scale;
/**
* Sequential scale (single hue progression)
*/
function createSequentialScale(baseColor: string, steps: number): Scale;
/**
* Categorical scale (distinct colors)
*/
function createCategoricalScale(categories: string[]): (category: string) => Color;Usage Examples:
// Common scale patterns
function createDivergingScale(colors = ['red', 'white', 'blue'], center = 0) {
return scale(colors).domain([-1, center, 1]);
}
function createSequentialScale(baseColor = 'blue', steps = 9) {
const light = chroma(baseColor).brighten(2);
const dark = chroma(baseColor).darken(2);
return scale([light, dark]).colors(steps);
}
function createCategoricalScale(categories) {
const colors = chroma.brewer.Set3; // Or other categorical palette
const mapping = {};
categories.forEach((cat, i) => {
mapping[cat] = chroma(colors[i % colors.length]);
});
return (category) => mapping[category] || chroma('#cccccc');
}
// Usage
const tempScale = createDivergingScale(['blue', 'white', 'red'], 20);
const populationColors = createSequentialScale('#0066cc', 7);
const categoryMapper = createCategoricalScale(['A', 'B', 'C', 'D']);
console.log(categoryMapper('A').hex()); // Color for category A