Diverging scales map continuous domains through a central neutral point to contrasting extremes. They are ideal for data with meaningful center points such as correlation coefficients, deviations from average, temperature anomalies, or any metric where both positive and negative variations from a baseline are significant.
The basic diverging scale uses a three-point domain (minimum, center, maximum) and maps to interpolated color schemes that diverge from a neutral center.
/**
* Creates a diverging scale with optional interpolation function
* @param interpolator - Function to interpolate through diverging colors
* @returns DivergingScale instance
*/
function scaleDiverging(interpolator?: InterpolatorFunction): DivergingScale;
interface DivergingScale {
/** Apply diverging transformation to domain value */
(value: number): any;
/** Get or set the three-point input domain [min, center, max] */
domain(): [number, number, number];
domain(domain: [number, number, number]): this;
/** Get or set the interpolation function */
interpolator(): InterpolatorFunction;
interpolator(interpolator: InterpolatorFunction): this;
/** Set range using interpolator between three values */
range(): [any, any, any];
range(range: [any, any, any]): this;
/** Set range with rounding interpolator */
rangeRound(range: [number, number, number]): this;
/** Enable or disable range clamping */
clamp(): boolean;
clamp(clamp: boolean): this;
/** Create independent copy */
copy(): DivergingScale;
/** Get or set unknown value handling */
unknown(): any;
unknown(value: any): this;
}Usage Examples:
import { scaleDiverging } from "d3-scale";
import { interpolateRdBu, interpolateSpectral } from "d3-scale-chromatic";
// Temperature anomaly scale
const tempAnomalyScale = scaleDiverging()
.domain([-5, 0, 5]) // [cold, normal, hot]
.interpolator(interpolateRdBu);
console.log(tempAnomalyScale(-3)); // Blue (cold)
console.log(tempAnomalyScale(0)); // White/neutral (normal)
console.log(tempAnomalyScale(3)); // Red (hot)
// Correlation scale
const correlationScale = scaleDiverging()
.domain([-1, 0, 1]) // [negative correlation, no correlation, positive correlation]
.interpolator(interpolateSpectral);
console.log(correlationScale(-0.8)); // Purple (strong negative)
console.log(correlationScale(0)); // Yellow (no correlation)
console.log(correlationScale(0.8)); // Red (strong positive)
// Asymmetric domain
const asymmetricScale = scaleDiverging()
.domain([-100, 10, 200]) // Center not in middle
.interpolator(interpolateRdBu);
console.log(asymmetricScale(10)); // Neutral color at center value
console.log(asymmetricScale(-50)); // Interpolated between min and center
console.log(asymmetricScale(105)); // Interpolated between center and maxDiverging scales with power transformations applied to the domain values.
/**
* Creates a diverging scale with power transformation
* @param interpolator - Optional interpolation function
* @returns DivergingScale with power transformation
*/
function scaleDivergingPow(interpolator?: InterpolatorFunction): DivergingScale;
/**
* Creates a diverging scale with square root transformation
* @param interpolator - Optional interpolation function
* @returns DivergingScale with sqrt transformation
*/
function scaleDivergingSqrt(interpolator?: InterpolatorFunction): DivergingScale;Both scales extend the base DivergingScale interface with additional methods:
interface DivergingPowerScale extends DivergingScale {
/** Get or set the power exponent */
exponent(): number;
exponent(exponent: number): this;
}Usage Examples:
import { scaleDivergingPow, scaleDivergingSqrt } from "d3-scale";
import { interpolatePiYG } from "d3-scale-chromatic";
// Power transformation for non-linear diverging mapping
const powerDivergingScale = scaleDivergingPow()
.domain([-1000, 0, 1000])
.exponent(0.5) // Square root transformation
.interpolator(interpolatePiYG);
// Values closer to center get more color resolution
console.log(powerDivergingScale(-100)); // More distinct from center
console.log(powerDivergingScale(-900)); // Less distinct from extreme
// Equivalent using sqrt scale
const sqrtDivergingScale = scaleDivergingSqrt()
.domain([-1000, 0, 1000])
.interpolator(interpolatePiYG);Diverging scale with logarithmic transformation, useful for diverging data spanning multiple orders of magnitude.
/**
* Creates a diverging scale with logarithmic transformation
* @param interpolator - Optional interpolation function
* @returns DivergingScale with log transformation
*/
function scaleDivergingLog(interpolator?: InterpolatorFunction): DivergingScale;Extends the base DivergingScale interface:
interface DivergingLogScale extends DivergingScale {
/** Get or set the logarithm base */
base(): number;
base(base: number): this;
}Diverging scale with symmetric logarithmic transformation for handling negative values and values near zero in diverging contexts.
/**
* Creates a diverging scale with symmetric logarithmic transformation
* @param interpolator - Optional interpolation function
* @returns DivergingScale with symlog transformation
*/
function scaleDivergingSymlog(interpolator?: InterpolatorFunction): DivergingScale;Extends the base DivergingScale interface:
interface DivergingSymlogScale extends DivergingScale {
/** Get or set the symlog constant */
constant(): number;
constant(constant: number): this;
}Usage Examples:
import { scaleDivergingLog, scaleDivergingSymlog } from "d3-scale";
import { interpolateBrBG } from "d3-scale-chromatic";
// Log diverging scale for data spanning orders of magnitude
const logDivergingScale = scaleDivergingLog()
.domain([0.001, 1, 1000]) // Center at 1, extremes at different orders
.base(10)
.interpolator(interpolateBrBG);
console.log(logDivergingScale(0.01)); // Brown (low extreme)
console.log(logDivergingScale(1)); // Neutral (center)
console.log(logDivergingScale(100)); // Green (high extreme)
// Symlog diverging scale including negative values
const symlogDivergingScale = scaleDivergingSymlog()
.domain([-1000, 0, 1000])
.constant(1)
.interpolator(interpolateBrBG);
console.log(symlogDivergingScale(-100)); // Brown (negative)
console.log(symlogDivergingScale(0)); // Neutral (zero)
console.log(symlogDivergingScale(100)); // Green (positive)Diverging scales work best with diverging color schemes from d3-scale-chromatic:
import { scaleDiverging } from "d3-scale";
import {
interpolateRdBu, // Red-Blue (temperature)
interpolateRdYlBu, // Red-Yellow-Blue
interpolateSpectral, // Purple-Yellow-Red
interpolateBrBG, // Brown-Green
interpolatePiYG, // Pink-Yellow-Green
interpolatePRGn, // Purple-Green
interpolateRdGy, // Red-Gray
interpolateRdYlGn // Red-Yellow-Green
} from "d3-scale-chromatic";
// Different schemes for different data types
const temperatureScale = scaleDiverging()
.domain([-20, 0, 40])
.interpolator(interpolateRdBu);
const correlationScale = scaleDiverging()
.domain([-1, 0, 1])
.interpolator(interpolateRdYlBu);
const anomalyScale = scaleDiverging()
.domain([-2, 0, 2])
.interpolator(interpolateRdGy);Common use cases for diverging scales in statistical visualization:
import { scaleDiverging } from "d3-scale";
import { interpolateRdBu } from "d3-scale-chromatic";
// Z-score visualization
const zScoreScale = scaleDiverging()
.domain([-3, 0, 3]) // Standard deviations from mean
.interpolator(interpolateRdBu);
// Election results (percentage difference from 50%)
const electionScale = scaleDiverging()
.domain([0, 50, 100]) // [opposition, tie, incumbent]
.interpolator(interpolateRdBu);
// Financial performance (percentage change)
const performanceScale = scaleDiverging()
.domain([-50, 0, 50]) // [loss, break-even, gain]
.interpolator(interpolateRdYlGn);Create custom three-color interpolators for specific use cases:
import { scaleDiverging } from "d3-scale";
import { interpolateRgb } from "d3-interpolate";
// Custom three-color diverging interpolator
const customDivergingScale = scaleDiverging()
.domain([-1, 0, 1])
.interpolator(t => {
if (t < 0.5) {
// Interpolate from blue to white (for negative values)
return interpolateRgb("darkblue", "white")(t * 2);
} else {
// Interpolate from white to red (for positive values)
return interpolateRgb("white", "darkred")((t - 0.5) * 2);
}
});
// Brand-specific colors
const brandDivergingScale = scaleDiverging()
.domain([-100, 0, 100])
.interpolator(t => {
if (t < 0.5) {
return interpolateRgb("#1f77b4", "#f0f0f0")(t * 2);
} else {
return interpolateRgb("#f0f0f0", "#ff7f0e")((t - 0.5) * 2);
}
});type InterpolatorFunction = (t: number) => any;