Skip to content
等值线图的绘制
概述
等值线图用于呈现二维标量场的等值线,常见于气象、地形、工程模拟等场景。在 Vue 3 项目中,可以通过 D3.js 或 @observablehq/plot(下文简称 Plot)生成等值线图。D3 提供 d3-contour、d3-geo 等底层模块,需要手动组合等值线计算、颜色映射和图例;Plot 在这些底层能力之上封装了默认行为,可大幅减少配置代码。
基本概念
数据格式
二维标量场数据通常包含三个字段:
width:网格列数height:网格行数values:一维数组,长度等于width × height,按行优先顺序排列
D3 的 d3.contours() 和 Plot 的 Plot.contour() 都直接使用这种格式。
工作原理
等值线生成依赖 Marching squares 算法,d3-contour 实现了该算法,并允许在指定阈值集合下计算等值线路径。Plot 在内部调用同样的算法,并自动选择默认阈值。
绘图时需要将数据网格坐标映射到像素坐标。D3 使用 d3.geoIdentity().scale() 创建恒等投影,将行列索引按比例缩放至指定的 SVG 宽度和高度。Plot 在内部完成了相似的坐标映射,调用方只需提供网格尺寸。
安装
D3.js
bash
npm install d3如果只需等值线相关模块,也可以按需安装。在 pnpm 或 cnpm 环境中,d3-contour 子包可能未被完整拉取,表现为 d3.contours 为 undefined。此时应改用 npm 安装,或显式安装 d3-contour 并在入口处引入。
在构建流程中,显式引入一次 d3-contour 可防止 tree-shaking 将其移除:
javascript
import * as d3 from 'd3';
import 'd3-contour';Plot
bash
npm install @observablehq/plot导入方式:
javascript
import * as Plot from "@observablehq/plot";基本用法
通过 D3.js 绘制
Vue 组件模板中提供挂载容器:
html
<div ref="svgContainerRef"></div>将等值线计算及 SVG 生成封装为一个函数(假设组件已获取到包含 width、height 和 values 的网格数据):
javascript
const drawContour = function () {
const n = data.width;
const m = data.height;
const width = 928;
const height = Math.round(m / n * width);
const path = d3.geoPath().projection(d3.geoIdentity().scale(width / n));
const contours = d3.contours().size([n, m]);
const color = d3.scaleSequential(d3.interpolateTurbo)
.domain(d3.extent(data.values))
.nice();
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto;");
svg.append("g")
.attr("stroke", "black")
.selectAll()
.data(color.ticks(20))
.join("path")
.attr("d", d => path(contours.contour(data.values, d)))
.attr("fill", color);
return svg.node();
};生成的 SVG 节点需在组件挂载后插入容器。在 Vue 3 组合式 API 中的典型做法:
javascript
const svgContainerRef = ref(null);
onMounted(() => {
const svgNode = drawContour();
svgContainerRef.value?.appendChild(svgNode);
});行为的说明:
d3.geoIdentity().scale(width / n)将数据坐标按显示宽度与列数的比例缩放,实现像素级对齐。d3.contours().size([n, m])根据行列数创建等值线生成器。d3.scaleSequential(d3.interpolateTurbo)将数值域映射到 Turbo 色带,domain取自数据的极值并做了取整扩展(.nice())。color.ticks(20)生成 20 个阈值,分别传递给.contour()得出每级等值线的几何路径。- 将路径数组绑定到
<path>元素,并用对应的阈值颜色填充。
生成效果示例:

这一方式赋予了开发者对阈值数量、颜色方案、图例的完全控制权,但图例、标注等需要自行添加。
使用 Plot 绘制
模板中同样预留一个容器:
html
<div ref="controlRef"></div>绘图函数(可直接在 onMounted 或响应式回调中调用):
javascript
const setcontrol = function () {
const plotDom = Plot.plot({
color: {
legend: true,
label: "Elevation (m)"
},
marks: [
Plot.contour(data.values, {
width: data.width,
height: data.height,
fill: Plot.identity,
stroke: "black"
})
]
});
controlRef.value?.appendChild(plotDom);
};核心行为:
Plot.plot()返回一个<figure>元素,其中包含 SVG、图例和坐标轴等。color配置开启图例并设置标签,Plot 会根据数据范围自动生成连续色标。Plot.contour标记接收原始数据和尺寸,fill: Plot.identity表示填充颜色由数据值直接决定,stroke: "black"为等值线加上黑色描边。Plot 内部封装了等值线计算、颜色映射与投影,无需显式设置contours和geoPath。
生成效果示例:

相比 D3 方案,Plot 将颜色图例、阈值分割、线宽等均纳入默认配置,代码量明显减少。
常用 API
D3.js
d3.contours().size([width, height])— 创建等值线生成器,指定网格尺寸。.contour(values, threshold)— 对给定values数组按指定阈值生成等值线几何对象。d3.geoIdentity().scale(k)— 创建一个恒等投影,缩放因子k控制网格坐标到像素坐标的映射。d3.geoPath().projection(projection)— 从等值线几何生成 SVG 路径字符串。d3.scaleSequential(d3.interpolateTurbo)— 顺序比例尺,搭配色带插值器,用于颜色编码。
Plot
Plot.plot(options)— 创建绘图,返回包含 SVG 和图例的<figure>元素。Plot.contour(values, options)— 等值线标记,options中可指定width、height、fill、stroke、thresholds等。
注意点
- 依赖完整性:在
pnpm或cnpm下安装 D3 时d3-contour可能缺失,导致d3.contours不可用。可改用npm安装,或显式安装d3-contour包并在入口文件引入,同时加上import 'd3-contour'防止 tree-shaking 删除。 - 数据格式:D3 和 Plot 的等值线接口都要求一维的
values数组,按行优先排列,并配合width、height描述网格尺寸。 - 颜色映射:使用 D3 时颜色比例尺的域和阈值数量完全由开发者控制;Plot 则通过
color选项调整色带和域,默认行为已覆盖大多数需求。 - 图例:D3 生成 SVG 时需要自行绘制图例;Plot 通过
color.legend开关即可控制内置图例的渲染。 - 挂载时机:采用 D3 方式时,生成的 SVG 节点必须在组件挂载后通过
appendChild插入容器,否则图形不会渲染。
限制
- D3 的方式要求理解
d3-contour、d3-geo和颜色比例尺的组合方式,对于仅需快速生成统计图表的场景来说学习成本较高。 - Plot 虽然配置简洁,但当需要修改等值线生成算法或将图形嵌入到自定义的 SVG 结构时,其封装层会带来一定约束,此时应回退到 D3。
- Plot 返回的是完整的
<figure>元素,若 Vue 组件需要直接操作内部 SVG 节点以添加动画或交互,则需额外解析 DOM。
应用
选择 D3 还是 Plot 取决于控制需求与开发效率:
- 如果需要精细控制等值线阈值间隔、图例样式,或需要将等值线图形嵌入已经设计好的 SVG 结构,应使用 D3。
- 如果只是快速生成带有默认图例和坐标轴的统计图表,且对细节控制要求不高,Plot 能以更低的配置成本完成工作。
参考链接
- D3.js 官方文档:https://d3js.org/
- Plot 官方文档:https://observablehq.com/plot/
- d3-contour 模块文档:https://d3js.org/d3-contour
- Observable 等值线图示例:https://observablehq.com/@d3/contours
