Skip to content

D3.js - 路径 API

SVG Path 是绘制自定义形状的基础,例如矩形、圆形、椭圆形、折线、多边形、直线和复杂曲线。SVG 的 <path> 元素在其 d 属性中使用一种特殊的微语言来定义形状的轮廓。这个轮廓可以被描边 (stroked)、填充 (filled)、用作剪切路径 (clipping path) 等。本章将探讨 D3 的 Path API,它有助于以编程方式生成这些路径定义。

D3 提供了两种主要方式来处理 Path:

  1. d3.path() 序列化器 (serializer):一个低级工具,类似于 Canvas API,用于逐步构建 Path 字符串。
  2. Path 生成器 (Path generators) (例如,d3.line(),d3.arc()):d3-shape 模块中更高级的函数,用于从数据生成 Path 字符串。这些通常用于图表。

要使用这些功能,您可以包含完整的 D3 库或特定的模块。

<!-- 选项 1: 包含完整的 D3 库 -->
<script src="https://d3js.org/d3.v7.min.js"></script>
<!-- 选项 2: 专门用于 d3.path() (如果未使用完整的 D3 库) -->
<script src="https://d3js.org/d3-path.v3.min.js"></script>
<!-- 选项 3: 用于像 d3.line() 这样的 Path 生成器 (如果未使用完整的 D3 库) -->
<script src="https://d3js.org/d3-shape.v3.min.js"></script>
<script>
// 包含库后的示例用法
// const path = d3.path();
// const line = d3.line();
</script>

d3.path() 创建一个对象,可用于构建 SVG Path 字符串。其主要方法如下:

  • d3.path() − 创建一个新的 Path 序列化器实例。
  • path.moveTo(x, y) − 将当前点移动到指定的 (x, y) 坐标,不绘制线条。(对应 SVG ‘M’ 命令)。
  • path.closePath() − 通过绘制从当前点到子路径起始点的直线来闭合当前子路径 (subpath)。(对应 SVG ‘Z’ 命令)。
  • path.lineTo(x, y) − 从当前点绘制一条直线到指定的 (x, y) 坐标。(对应 SVG ‘L’ 命令)。
  • path.quadraticCurveTo(cpx, cpy, x, y) − 从当前点绘制一条二次贝塞尔曲线 (quadratic Bézier curve) 到 (x, y),其中 (cpx, cpy) 是控制点 (control point)。(对应 SVG ‘Q’ 命令)。
  • path.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x, y) − 从当前点绘制一条三次贝塞尔曲线 (cubic Bézier curve) 到 (x, y),其中 (cpx1, cpy1) 和 (cpx2, cpy2) 是控制点。(对应 SVG ‘C’ 命令)。
  • path.arcTo(x1, y1, x2, y2, radius) − 绘制一个给定半径的圆弧 (arc),该圆弧与从当前点到 (x1, y1) 的线段以及从 (x1, y1) 到 (x2, y2) 的线段相切 (tangential)。(对应 SVG ‘A’ 命令,但行为更类似于 Canvas 的 arcTo)。
  • path.arc(x, y, radius, startAngle, endAngle[, anticlockwise]) − 绘制一个以 (x, y) 为中心、指定半径的圆弧,从 startAngle 到 endAngle。角度以弧度 (radians) 为单位。可选的 anticlockwise 布尔值 (默认为 false) 决定方向。(对应 SVG ‘A’ 命令,构建方式不同)。
  • path.rect(x, y, width, height) − 创建一个新的矩形子路径 (subpath)。它先移动到 (x, y),然后绘制直线到 (x + width, y),(x + width, y + height),(x, y + height),并闭合路径。(使用 SVG ‘M’ 和 ‘L’ 命令)。
  • path.toString() − 返回构建的 Path 的字符串表示形式,适合在 SVG 的 d 属性中使用。

虽然 d3.path() 用于手动构建 Path,但 d3.line() (来自 d3-shape) 是一种 Path 生成器,非常适合从数据创建折线图。让我们创建一个简单的线条。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>D3.js Line Path Example</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
.line-path {
fill: none;
stroke: green;
stroke-width: 2px;
}
</style>
</head>
<body>
<svg width="600" height="200">
<path class="line-path" transform="translate(50, 50)"></path>
</svg>
<script>
const data = [
{x: 0, y: 20},
{x: 50, y: 30},
{x: 100, y: 50},
{x: 200, y: 60},
{x: 300, y: 90}
];
// 创建一个线条生成器
const lineGenerator = d3.line()
.x(d => d.x) // x 坐标的访问器
.y(d => d.y); // y 坐标的访问器
// 生成 Path 字符串
const pathString = lineGenerator(data);
// 选择 Path 元素并设置其 'd' 属性
d3.select('.line-path')
.attr('d', pathString);
</script>
</body>
</html>

当您在浏览器中打开此 HTML 文件时,您将看到根据提供的数据点绘制的绿色线条。d3.line() 生成器简化了为常见图表类型创建复杂的 Path 字符串的过程。

Path 是大多数 D3.js 可视化的核心:

  • 折线图 (Line charts)、面积图 (area charts) 和流图 (streamgraphs) 使用 Path 生成器。
  • 散点图中的自定义符号可以使用 Path 定义。
  • 地理地图 (GeoJSON 特征) 被渲染为 Path。
  • 复杂的图表如桑基图 (Sankey diagrams) 或弦图 (chord diagrams) 都严重依赖于 Path。

有关 SVG Path 的更多详细信息,请参阅 MDN SVG Path 教程。对于 D3 Path 生成器,请查阅 d3-shape 文档。