or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

animation.mdcolor-interpolation.mdcolor-schemes.mddata-processing.mdformat.mdgeo.mdindex.mdinteractions.mdlayouts.mdscales-axes.mdselection.mdshapes.mdtime.md
tile.json

scales-axes.mddocs/

Scales and Axes

Scales are functions that map abstract data dimensions to visual representations. Axes create human-readable reference marks for scales. Together they form the foundation for creating meaningful data visualizations with proper scaling and labeling.

Capabilities

Linear Scales

Continuous scales with linear mathematical relationships between domain and range.

/**
 * Create a continuous linear scale
 * @returns Linear scale function
 */
function scaleLinear(): ScaleLinear<number, number, never>;

interface ScaleLinear<Domain extends NumberValue, Range, Output> {
  /**
   * Scale a value from domain to range
   * @param value - Input value in domain
   * @returns Scaled value in range
   */
  (value: Domain): Output;
  
  /**
   * Invert a value from range back to domain
   * @param value - Value in range to invert
   * @returns Original domain value
   */
  invert(value: Range): Domain;
  
  /**
   * Get or set the input domain
   * @param domain - Array of domain values [min, max]
   * @returns Scale for chaining or current domain
   */
  domain(): Domain[];
  domain(domain: Iterable<Domain>): ScaleLinear<Domain, Range, Output>;
  
  /**
   * Get or set the output range
   * @param range - Array of range values [min, max]
   * @returns Scale for chaining or current range
   */
  range(): Range[];
  range(range: Iterable<Range>): ScaleLinear<Domain, Range, Output>;
  
  /**
   * Set range and enable rounding to integers
   * @param range - Array of range values
   * @returns Scale for chaining
   */
  rangeRound(range: Iterable<Range>): ScaleLinear<Domain, Range, Output>;
  
  /**
   * Enable or disable clamping to domain/range bounds
   * @param clamp - Whether to enable clamping
   * @returns Scale for chaining or current clamp setting
   */
  clamp(): boolean;
  clamp(clamp: boolean): ScaleLinear<Domain, Range, Output>;
  
  /**
   * Generate representative values from domain
   * @param count - Approximate number of ticks
   * @returns Array of tick values
   */
  ticks(count?: number): Domain[];
  
  /**
   * Format tick values for human consumption
   * @param count - Number of ticks for formatting hints
   * @param specifier - Format specifier string
   * @returns Formatting function
   */
  tickFormat(count?: number, specifier?: string): (d: Domain) => string;
  
  /**
   * Extend domain to nice round numbers
   * @param count - Target number of ticks
   * @returns Scale for chaining
   */
  nice(count?: number): ScaleLinear<Domain, Range, Output>;
  
  /**
   * Create a copy of this scale
   * @returns New scale with same configuration
   */
  copy(): ScaleLinear<Domain, Range, Output>;
}

/**
 * Create identity scale where domain equals range
 * @returns Identity scale
 */
function scaleIdentity(): ScaleLinear<number, number, number>;

/**
 * Create radial scale (like linear, but sqrt transform on range)
 * @returns Radial scale
 */
function scaleRadial(): ScaleRadial<number, number, number>;

Usage Examples:

import { scaleLinear } from "d3";

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

console.log(xScale(50)); // 250 (middle of range)
console.log(xScale.invert(250)); // 50 (back to domain)

// Scale with nice domain
const yScale = scaleLinear()
  .domain([0.201, 0.956])
  .range([300, 0])     // Flipped for SVG coordinates
  .nice();             // Rounds domain to [0.2, 1]

Power and Logarithmic Scales

Non-linear scales for exponential and logarithmic data relationships.

/**
 * Create power scale (y = mx^k + b)
 * @returns Power scale
 */
function scalePow(): ScalePower<number, number, never>;

/**
 * Create square root scale (power scale with exponent 0.5)
 * @returns Square root scale
 */
function scaleSqrt(): ScalePower<number, number, never>;

interface ScalePower<Domain extends NumberValue, Range, Output> extends ScaleLinear<Domain, Range, Output> {
  /**
   * Get or set the power exponent
   * @param exponent - Power exponent (default 1)
   * @returns Scale for chaining or current exponent
   */
  exponent(): number;
  exponent(exponent: number): ScalePower<Domain, Range, Output>;
}

/**
 * Create logarithmic scale
 * @returns Logarithmic scale
 */
function scaleLog(): ScaleLogarithmic<number, number, never>;

interface ScaleLogarithmic<Domain extends NumberValue, Range, Output> extends ScaleLinear<Domain, Range, Output> {
  /**
   * Get or set the logarithm base
   * @param base - Logarithm base (default 10)
   * @returns Scale for chaining or current base
   */
  base(): number;
  base(base: number): ScaleLogarithmic<Domain, Range, Output>;
}

/**
 * Create symmetric logarithmic scale
 * @returns Symlog scale  
 */
function scaleSymlog(): ScaleSymLog<number, number, never>;

interface ScaleSymLog<Domain extends NumberValue, Range, Output> extends ScaleLinear<Domain, Range, Output> {
  /**
   * Get or set the symlog constant
   * @param constant - Linear threshold constant
   * @returns Scale for chaining or current constant
   */
  constant(): number;
  constant(constant: number): ScaleSymLog<Domain, Range, Output>;
}

Time Scales

Scales for temporal data with time-specific ticking and formatting.

/**
 * Create time scale for local time
 * @returns Time scale
 */
function scaleTime(): ScaleTime<Date, number, never>;

/**
 * Create time scale for UTC time
 * @returns UTC time scale
 */
function scaleUtc(): ScaleTime<Date, number, never>;

interface ScaleTime<Domain extends Date, Range, Output> {
  (value: Domain): Output;
  invert(value: Range): Domain;
  domain(): Domain[];
  domain(domain: Iterable<Domain>): ScaleTime<Domain, Range, Output>;
  range(): Range[];
  range(range: Iterable<Range>): ScaleTime<Domain, Range, Output>;
  
  /**
   * Generate time-based ticks
   * @param count - Target number of ticks
   * @returns Array of Date tick values
   */
  ticks(count?: number): Domain[];
  ticks(interval: TimeInterval): Domain[];
  
  /**
   * Format time tick values
   * @param count - Number of ticks for formatting hints
   * @param specifier - Time format specifier
   * @returns Time formatting function
   */
  tickFormat(count?: number, specifier?: string): (d: Domain) => string;
  
  /**
   * Extend domain to nice time boundaries
   * @param count - Target number of ticks
   * @returns Scale for chaining
   */
  nice(count?: number): ScaleTime<Domain, Range, Output>;
  nice(interval: TimeInterval): ScaleTime<Domain, Range, Output>;
  
  copy(): ScaleTime<Domain, Range, Output>;
}

Ordinal Scales

Scales for discrete data with categorical domains and discrete or continuous ranges.

/**
 * Create ordinal scale for categorical data
 * @returns Ordinal scale
 */
function scaleOrdinal<Domain extends string = string, Range = string>(): ScaleOrdinal<Domain, Range, never>;

interface ScaleOrdinal<Domain, Range, Output> {
  (value: Domain): Output;
  
  /**
   * Get or set the discrete domain
   * @param domain - Array of discrete domain values
   * @returns Scale for chaining or current domain
   */
  domain(): Domain[];
  domain(domain: Iterable<Domain>): ScaleOrdinal<Domain, Range, Output>;
  
  /**
   * Get or set the discrete range
   * @param range - Array of discrete range values
   * @returns Scale for chaining or current range
   */
  range(): Range[];
  range(range: Iterable<Range>): ScaleOrdinal<Domain, Range, Output>;
  
  /**
   * Get or set unknown value handler
   * @param value - Value to return for unknown domain values
   * @returns Scale for chaining or current unknown value
   */
  unknown(): Output;
  unknown(value: Output): ScaleOrdinal<Domain, Range, Output>;
  
  copy(): ScaleOrdinal<Domain, Range, Output>;
}

/**
 * Create band scale for creating bars/columns with spacing
 * @returns Band scale
 */
function scaleBand(): ScaleBand<string>;

interface ScaleBand<Domain extends string> {
  (value: Domain): number | undefined;
  
  domain(): Domain[];
  domain(domain: Iterable<Domain>): ScaleBand<Domain>;
  range(): [number, number];
  range(range: [number, number]): ScaleBand<Domain>;
  
  /**
   * Get the bandwidth (width of each band)
   * @returns Width of each band
   */
  bandwidth(): number;
  
  /**
   * Get the step (distance between band starts)
   * @returns Distance between start of adjacent bands
   */
  step(): number;
  
  /**
   * Get or set inner padding between bands
   * @param padding - Padding as fraction of step
   * @returns Scale for chaining or current padding
   */
  paddingInner(): number;
  paddingInner(padding: number): ScaleBand<Domain>;
  
  /**
   * Get or set outer padding before first and after last band
   * @param padding - Padding as fraction of step
   * @returns Scale for chaining or current padding
   */
  paddingOuter(): number;
  paddingOuter(padding: number): ScaleBand<Domain>;
  
  /**
   * Set inner and outer padding simultaneously
   * @param padding - Padding as fraction of step
   * @returns Scale for chaining
   */
  padding(padding: number): ScaleBand<Domain>;
  
  copy(): ScaleBand<Domain>;
}

/**
 * Create point scale for positioning elements along a line
 * @returns Point scale
 */
function scalePoint(): ScalePoint<string>;

interface ScalePoint<Domain extends string> {
  (value: Domain): number | undefined;
  
  domain(): Domain[];
  domain(domain: Iterable<Domain>): ScalePoint<Domain>;
  range(): [number, number];
  range(range: [number, number]): ScalePoint<Domain>;
  
  /**
   * Get the step (distance between points)
   * @returns Distance between adjacent points
   */
  step(): number;
  
  /**
   * Get or set padding before first and after last point
   * @param padding - Padding as fraction of step
   * @returns Scale for chaining or current padding
   */
  padding(): number;
  padding(padding: number): ScalePoint<Domain>;
  
  copy(): ScalePoint<Domain>;
}

Quantize Scales

Scales that map continuous domains to discrete ranges through quantization.

/**
 * Create quantize scale (uniform quantization)
 * @returns Quantize scale
 */
function scaleQuantize<Range = number>(): ScaleQuantize<Range>;

interface ScaleQuantize<Range> {
  (value: number): Range;
  
  /**
   * Get domain values corresponding to given range value
   * @param value - Range value to invert
   * @returns Domain interval [x0, x1]
   */
  invertExtent(value: Range): [number, number] | [undefined, undefined];
  
  domain(): [number, number];
  domain(domain: [number, number]): ScaleQuantize<Range>;
  range(): Range[];
  range(range: Iterable<Range>): ScaleQuantize<Range>;
  
  /**
   * Get array of threshold values
   * @returns Array of threshold values
   */
  thresholds(): number[];
  
  copy(): ScaleQuantize<Range>;
}

/**
 * Create quantile scale (quantile-based quantization)
 * @returns Quantile scale
 */
function scaleQuantile<Range = number>(): ScaleQuantile<Range>;

interface ScaleQuantile<Range> {
  (value: number): Range;
  
  invertExtent(value: Range): [number, number] | [undefined, undefined];
  
  domain(): number[];
  domain(domain: Iterable<number>): ScaleQuantile<Range>;
  range(): Range[];
  range(range: Iterable<Range>): ScaleQuantile<Range>;
  
  /**
   * Get quantile thresholds
   * @returns Array of quantile thresholds  
   */
  quantiles(): number[];
  
  copy(): ScaleQuantile<Range>;
}

/**
 * Create threshold scale (arbitrary thresholds)
 * @returns Threshold scale
 */
function scaleThreshold<Domain extends number | string | Date, Range = number>(): ScaleThreshold<Domain, Range>;

interface ScaleThreshold<Domain, Range> {
  (value: Domain): Range;
  
  invertExtent(value: Range): [Domain, Domain] | [undefined, undefined];
  
  domain(): Domain[];
  domain(domain: Iterable<Domain>): ScaleThreshold<Domain, Range>;
  range(): Range[];
  range(range: Iterable<Range>): ScaleThreshold<Domain, Range>;
  
  copy(): ScaleThreshold<Domain, Range>;
}

Axis Generators

Functions that create SVG axis elements with ticks, labels, and gridlines.

/**
 * Create top-oriented axis (ticks above horizontal line)
 * @param scale - Scale function for the axis
 * @returns Axis generator function
 */
function axisTop<Domain>(scale: AxisScale<Domain>): Axis<Domain>;

/**
 * Create right-oriented axis (ticks right of vertical line)
 * @param scale - Scale function for the axis
 * @returns Axis generator function
 */
function axisRight<Domain>(scale: AxisScale<Domain>): Axis<Domain>;

/**
 * Create bottom-oriented axis (ticks below horizontal line)
 * @param scale - Scale function for the axis  
 * @returns Axis generator function
 */
function axisBottom<Domain>(scale: AxisScale<Domain>): Axis<Domain>;

/**
 * Create left-oriented axis (ticks left of vertical line)
 * @param scale - Scale function for the axis
 * @returns Axis generator function
 */
function axisLeft<Domain>(scale: AxisScale<Domain>): Axis<Domain>;

interface Axis<Domain> {
  /**
   * Render the axis to a selection
   * @param context - Selection to render axis into
   */
  (context: Selection<any, any, any, any>): void;
  
  /**
   * Get or set the scale for this axis
   * @param scale - Scale function
   * @returns Axis for chaining or current scale
   */
  scale(): AxisScale<Domain>;
  scale(scale: AxisScale<Domain>): Axis<Domain>;
  
  /**
   * Set tick count and format simultaneously
   * @param count - Number of ticks
   * @param specifier - Format specifier
   * @returns Axis for chaining
   */
  ticks(count?: number, specifier?: string): Axis<Domain>;
  ticks(interval: any, specifier?: string): Axis<Domain>;
  
  /**
   * Set arguments passed to scale.ticks and scale.tickFormat
   * @param args - Arguments for tick generation
   * @returns Axis for chaining
   */
  tickArguments(): any[];
  tickArguments(args: any[]): Axis<Domain>;
  
  /**
   * Set explicit tick values
   * @param values - Array of tick values, or null for scale default
   * @returns Axis for chaining or current tick values
   */
  tickValues(): Domain[] | null;
  tickValues(values: Iterable<Domain> | null): Axis<Domain>;
  
  /**
   * Set explicit tick format function
   * @param format - Format function, or null for scale default
   * @returns Axis for chaining or current format function
   */
  tickFormat(): ((d: Domain, i: number) => string) | null;
  tickFormat(format: (d: Domain, i: number) => string | null): Axis<Domain>;
  
  /**
   * Set size of inner and outer ticks
   * @param size - Tick size in pixels
   * @returns Axis for chaining or current tick size
   */
  tickSize(): number;
  tickSize(size: number): Axis<Domain>;
  
  /**
   * Set size of inner ticks only
   * @param size - Inner tick size in pixels
   * @returns Axis for chaining or current inner tick size
   */
  tickSizeInner(): number;
  tickSizeInner(size: number): Axis<Domain>;
  
  /**
   * Set size of outer ticks only (domain path ends)
   * @param size - Outer tick size in pixels
   * @returns Axis for chaining or current outer tick size
   */
  tickSizeOuter(): number;
  tickSizeOuter(size: number): Axis<Domain>;
  
  /**
   * Set padding between ticks and labels
   * @param padding - Padding in pixels
   * @returns Axis for chaining or current padding
   */
  tickPadding(): number;
  tickPadding(padding: number): Axis<Domain>;
  
  /**
   * Set pixel offset for crisp edges
   * @param offset - Pixel offset
   * @returns Axis for chaining or current offset
   */
  offset(): number;
  offset(offset: number): Axis<Domain>;
}

Usage Examples:

import { scaleLinear, axisBottom, axisLeft } from "d3";

// Create scales
const xScale = scaleLinear()
  .domain([0, 100])
  .range([0, 400]);

const yScale = scaleLinear()
  .domain([0, 50])
  .range([300, 0]);

// Create axes
const xAxis = axisBottom(xScale)
  .ticks(5)
  .tickFormat(d => d + "%");

const yAxis = axisLeft(yScale)
  .ticks(4)
  .tickSize(-400); // Negative size creates gridlines

// Apply to selections
svg.append("g")
  .attr("transform", "translate(0, 300)")
  .call(xAxis);

svg.append("g")
  .call(yAxis);

Types

// Core scale types
type NumberValue = number | { valueOf(): number; };

type AxisScale<Domain> = {
  (x: Domain): number | undefined;
  domain(): Domain[];
  range(): number[];
  copy(): AxisScale<Domain>;
  bandwidth?(): number;
  ticks?(count?: number): Domain[];
  tickFormat?(count?: number, specifier?: string): (d: Domain) => string;
};

// Time interval type for time scales
interface TimeInterval {
  (date: Date): Date;
  floor(date: Date): Date;
  ceil(date: Date): Date;
  round(date: Date): Date;
  offset(date: Date, step?: number): Date;
  range(start: Date, stop: Date, step?: number): Date[];
}

// Scale domains and ranges
type ScaleContinuousNumeric<Range, Output> = ScaleLinear<number, Range, Output>;
type ScaleSequential<Output> = (t: number) => Output;
type ScaleDiverging<Output> = (t: number) => Output;