D3.js 比例尺 #
比例尺是 D3.js 中将数据值映射到可视空间的函数。它们将抽象的数据值转换为像素位置、颜色或其他视觉属性,是数据可视化的核心组件。
比例尺基础 #
核心概念 #
text
┌─────────────────────────────────────────────────────────────┐
│ 比例尺映射原理 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Domain(定义域) Range(值域) │
│ 数据值范围 ──► 视觉值范围 │
│ │
│ [0, 100] ──► [0, 500] │
│ │
│ scale(50) = 250 │
│ │
└─────────────────────────────────────────────────────────────┘
比例尺类型 #
| 类型 | 描述 | 适用场景 |
|---|---|---|
| scaleLinear | 线性比例尺 | 连续数值数据 |
| scaleBand | 序数比例尺 | 分类数据 |
| scalePoint | 点比例尺 | 离散点位置 |
| scaleOrdinal | 序数比例尺 | 离散值映射 |
| scaleTime | 时间比例尺 | 时间序列数据 |
| scaleLog | 对数比例尺 | 指数增长数据 |
| scalePow | 幂比例尺 | 非线性关系 |
| scaleQuantize | 量化比例尺 | 连续转离散 |
| scaleQuantile | 分位数比例尺 | 百分位分布 |
| scaleThreshold | 阈值比例尺 | 自定义分段 |
线性比例尺 scaleLinear #
基本用法 #
javascript
const xScale = d3.scaleLinear()
.domain([0, 100])
.range([0, 500]);
xScale(0);
xScale(50);
xScale(100);
xScale.invert(250);
设置定义域和值域 #
javascript
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([height, 0]);
const xScale = d3.scaleLinear()
.domain([0, 100])
.range([margin.left, width - margin.right]);
clamp 方法 #
限制输出范围:
javascript
const scale = d3.scaleLinear()
.domain([0, 100])
.range([0, 500])
.clamp(true);
scale(150);
scale(-10);
nice 方法 #
优化定义域边界:
javascript
const scale = d3.scaleLinear()
.domain([0.123, 99.876])
.nice();
scale.domain();
rangeRound 方法 #
四舍五入输出值:
javascript
const scale = d3.scaleLinear()
.domain([0, 100])
.rangeRound([0, 500]);
scale(33.3);
ticks 和 tickFormat #
生成刻度和格式化:
javascript
const scale = d3.scaleLinear()
.domain([0, 100])
.range([0, 500]);
scale.ticks(5);
scale.tickFormat(5, '.0f')(50);
scale.tickFormat(5, '.1f')(50);
序数比例尺 scaleBand #
基本用法 #
javascript
const xScale = d3.scaleBand()
.domain(['A', 'B', 'C', 'D', 'E'])
.range([0, 500]);
xScale('A');
xScale('B');
xScale('C');
bandwidth 方法 #
获取每个带的宽度:
javascript
const xScale = d3.scaleBand()
.domain(['A', 'B', 'C'])
.range([0, 300]);
xScale.bandwidth();
padding 方法 #
设置内边距和外边距:
javascript
const xScale = d3.scaleBand()
.domain(['A', 'B', 'C'])
.range([0, 300])
.padding(0.2);
xScale.paddingInner();
xScale.paddingOuter();
xScale.step();
paddingInner 和 paddingOuter #
分别设置内外边距:
javascript
const xScale = d3.scaleBand()
.domain(['A', 'B', 'C'])
.range([0, 300])
.paddingInner(0.1)
.paddingOuter(0.2);
align 方法 #
对齐方式:
javascript
const xScale = d3.scaleBand()
.domain(['A', 'B', 'C'])
.range([0, 300])
.align(0.5);
点比例尺 scalePoint #
基本用法 #
javascript
const xScale = d3.scalePoint()
.domain(['A', 'B', 'C', 'D'])
.range([0, 300]);
xScale('A');
xScale('B');
padding 方法 #
javascript
const xScale = d3.scalePoint()
.domain(['A', 'B', 'C'])
.range([0, 300])
.padding(0.5);
step 方法 #
获取步长:
javascript
const xScale = d3.scalePoint()
.domain(['A', 'B', 'C'])
.range([0, 300]);
xScale.step();
序数比例尺 scaleOrdinal #
基本用法 #
javascript
const colorScale = d3.scaleOrdinal()
.domain(['A', 'B', 'C'])
.range(['red', 'green', 'blue']);
colorScale('A');
colorScale('B');
colorScale('C');
colorScale('D');
unknown 方法 #
设置未知值的映射:
javascript
const colorScale = d3.scaleOrdinal()
.domain(['A', 'B', 'C'])
.range(['red', 'green', 'blue'])
.unknown('gray');
colorScale('X');
预设颜色方案 #
javascript
const colorScale = d3.scaleOrdinal(d3.schemeCategory10);
const colorScale = d3.scaleOrdinal(d3.schemeTableau10);
const colorScale = d3.scaleOrdinal()
.domain(data.map(d => d.category))
.range(d3.schemeSet2);
时间比例尺 scaleTime #
基本用法 #
javascript
const xScale = d3.scaleTime()
.domain([new Date(2020, 0, 1), new Date(2020, 11, 31)])
.range([0, 500]);
xScale(new Date(2020, 5, 15));
设置时间范围 #
javascript
const xScale = d3.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([margin.left, width - margin.right]);
ticks 方法 #
javascript
const scale = d3.scaleTime()
.domain([new Date(2020, 0, 1), new Date(2020, 11, 31)])
.range([0, 500]);
scale.ticks(d3.timeMonth.every(1));
scale.ticks(d3.timeWeek.every(2));
scale.ticks(d3.timeDay.every(7));
nice 方法 #
javascript
const scale = d3.scaleTime()
.domain([new Date(2020, 0, 15), new Date(2020, 11, 20)])
.nice(d3.timeMonth);
scale.domain();
对数比例尺 scaleLog #
基本用法 #
javascript
const scale = d3.scaleLog()
.domain([1, 10000])
.range([0, 500]);
scale(1);
scale(10);
scale(100);
scale(1000);
scale(10000);
base 方法 #
设置底数:
javascript
const scale = d3.scaleLog()
.domain([1, 1000])
.range([0, 500])
.base(2);
scale(1);
scale(2);
scale(4);
scale(8);
ticks 方法 #
javascript
const scale = d3.scaleLog()
.domain([1, 10000])
.range([0, 500]);
scale.ticks();
幂比例尺 scalePow #
基本用法 #
javascript
const scale = d3.scalePow()
.domain([0, 100])
.range([0, 500])
.exponent(2);
scale(0);
scale(50);
scale(100);
scaleSqrt 快捷方法 #
javascript
const scale = d3.scaleSqrt()
.domain([0, 100])
.range([0, 500]);
scale(25);
scale(100);
量化比例尺 scaleQuantize #
基本用法 #
将连续值映射到离散值:
javascript
const colorScale = d3.scaleQuantize()
.domain([0, 100])
.range(['low', 'medium', 'high']);
colorScale(0);
colorScale(33);
colorScale(66);
colorScale(100);
invertExtent 方法 #
获取值对应的范围:
javascript
const scale = d3.scaleQuantize()
.domain([0, 100])
.range(['A', 'B', 'C']);
scale.invertExtent('A');
scale.invertExtent('B');
scale.invertExtent('C');
分位数比例尺 scaleQuantile #
基本用法 #
根据数据分布映射:
javascript
const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const scale = d3.scaleQuantile()
.domain(data)
.range(['low', 'medium', 'high']);
scale(1);
scale(5);
scale(10);
quantiles 方法 #
获取分位点:
javascript
const scale = d3.scaleQuantile()
.domain([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
.range(['A', 'B', 'C', 'D']);
scale.quantiles();
阈值比例尺 scaleThreshold #
基本用法 #
自定义阈值分段:
javascript
const colorScale = d3.scaleThreshold()
.domain([0, 50, 100])
.range(['blue', 'green', 'yellow', 'red']);
colorScale(-10);
colorScale(25);
colorScale(75);
colorScale(150);
invertExtent 方法 #
javascript
const scale = d3.scaleThreshold()
.domain([0, 50, 100])
.range(['A', 'B', 'C', 'D']);
scale.invertExtent('B');
连续比例尺 scaleSequential #
基本用法 #
使用插值器:
javascript
const colorScale = d3.scaleSequential()
.domain([0, 100])
.interpolator(d3.interpolateViridis);
colorScale(0);
colorScale(50);
colorScale(100);
预设插值器 #
javascript
d3.interpolateViridis
d3.interpolatePlasma
d3.interpolateMagma
d3.interpolateInferno
d3.interpolateWarm
d3.interpolateCool
d3.interpolateRainbow
d3.interpolateSinebow
自定义插值器 #
javascript
const colorScale = d3.scaleSequential()
.domain([0, 100])
.interpolator(t => d3.interpolate('blue', 'red')(t));
发散比例尺 scaleDiverging #
基本用法 #
javascript
const colorScale = d3.scaleDiverging()
.domain([-100, 0, 100])
.interpolator(d3.interpolateRdYlBu);
colorScale(-100);
colorScale(0);
colorScale(100);
比例尺实战示例 #
柱状图比例尺 #
javascript
const data = [
{ category: 'A', value: 30 },
{ category: 'B', value: 80 },
{ category: 'C', value: 50 }
];
const xScale = d3.scaleBand()
.domain(data.map(d => d.category))
.range([margin.left, width - margin.right])
.padding(0.2);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.nice()
.range([height - margin.bottom, margin.top]);
svg.selectAll('rect')
.data(data)
.join('rect')
.attr('x', d => xScale(d.category))
.attr('y', d => yScale(d.value))
.attr('width', xScale.bandwidth())
.attr('height', d => height - margin.bottom - yScale(d.value));
散点图比例尺 #
javascript
const data = [
{ x: 10, y: 20, size: 5 },
{ x: 30, y: 40, size: 10 },
{ x: 50, y: 60, size: 15 }
];
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.x)])
.range([margin.left, width - margin.right]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.y)])
.range([height - margin.bottom, margin.top]);
const sizeScale = d3.scaleSqrt()
.domain([0, d3.max(data, d => d.size)])
.range([2, 20]);
svg.selectAll('circle')
.data(data)
.join('circle')
.attr('cx', d => xScale(d.x))
.attr('cy', d => yScale(d.y))
.attr('r', d => sizeScale(d.size));
时间序列图比例尺 #
javascript
const data = [
{ date: new Date(2020, 0, 1), value: 10 },
{ date: new Date(2020, 1, 1), value: 20 },
{ date: new Date(2020, 2, 1), value: 15 }
];
const xScale = d3.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([margin.left, width - margin.right]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([height - margin.bottom, margin.top]);
热力图比例尺 #
javascript
const data = [
{ row: 'A', col: 'X', value: 10 },
{ row: 'A', col: 'Y', value: 20 },
{ row: 'B', col: 'X', value: 30 },
{ row: 'B', col: 'Y', value: 40 }
];
const xScale = d3.scaleBand()
.domain(['X', 'Y'])
.range([0, 200]);
const yScale = d3.scaleBand()
.domain(['A', 'B'])
.range([0, 200]);
const colorScale = d3.scaleSequential()
.domain([0, d3.max(data, d => d.value)])
.interpolator(d3.interpolateBlues);
比例尺方法速查表 #
| 方法 | 描述 | 示例 |
|---|---|---|
| domain | 设置定义域 | .domain([0, 100]) |
| range | 设置值域 | .range([0, 500]) |
| invert | 反向映射 | scale.invert(250) |
| clamp | 限制输出范围 | .clamp(true) |
| nice | 优化边界 | .nice() |
| rangeRound | 四舍五入 | .rangeRound([0, 500]) |
| ticks | 生成刻度 | .ticks(5) |
| tickFormat | 刻度格式化 | .tickFormat(5, '.0f') |
| copy | 复制比例尺 | scale.copy() |
下一步 #
现在你已经掌握了 D3.js 比例尺的使用,接下来学习 SVG 基础,了解如何在 D3.js 中创建 SVG 图形!
最后更新:2026-03-28