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