JavaScript library for color conversions and color scale generation with zero dependencies
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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