Skip to content

D3.js - SVG 变换

可缩放矢量图形(SVG)提供了强大的选项来变换单个 SVG 元素或元素组。这些变换包括平移(移动)、缩放(改变大小)、旋转和倾斜。D3.js 使得基于数据动态应用这些变换变得容易。

SVG 元素使用 transform 属性来指定变换。该属性的值是一个字符串,包含一个或多个变换定义。常见的变换函数有:

  • 平移(Translate):translate(tx [ty]) - 将元素沿 x 轴移动 tx,沿 y 轴移动 ty。如果未提供 ty,则默认为 0。示例:translate(30 30) 或 translate(50)(沿 x 轴移动 50,沿 y 轴移动 0)。
  • 旋转(Rotate):rotate(angle [cx cy]) - 将元素绕中心点 (cx, cy) 旋转 angle 度。如果未指定 cx 和 cy,则旋转围绕元素当前坐标系的原点 (0,0) 进行。示例:rotate(60) 或 rotate(45 10 10)。
  • 缩放(Scale):scale(sx [sy]) - 将元素沿 x 轴按因子 sx 缩放,沿 y 轴按因子 sy 缩放。如果未提供 sy,则默认为 sx 的值(均匀缩放)。示例:scale(2)(大小加倍)或 scale(1.5 0.5)。
  • 沿 X 轴倾斜(SkewX):skewX(angle) - 将元素沿 x 轴倾斜 angle 度。
  • 沿 Y 轴倾斜(SkewY):skewY(angle) - 将元素沿 y 轴倾斜 angle 度。

直接在 SVG 标记中应用平移变换的 SVG 矩形示例:

<svg width="200" height="150">
<rect x="10" y="10" width="50" height="50" fill="green" transform="translate(30 30)">
</rect>
<!-- 矩形的左上角,原位于 (10,10),应用变换后实际将在 (40,40) -->
</svg>

可以通过在 transform 属性中列出多个变换,用空格分隔来应用。它们从左到右依次应用。

<svg width="200" height="200">
<rect x="20" y="20" width="60" height="60" fill="blue"
transform="translate(50 50) rotate(45)">
<!-- 先平移,然后绕其新的 (0,0) 点(即平移后的点)旋转 -->
</rect>
</svg>

变换也可以应用于 SVG 组元素(<g>)。这非常有用,因为组内的所有子元素都会继承该变换。

<svg width="300" height="300">
<g transform="translate(100,100) rotate(30)">
<rect x="0" y="0" width="80" height="40" fill="green"></rect>
<circle cx="40" cy="60" r="20" fill="red"></circle>
<!-- 矩形和圆形都被平移,然后一起旋转 -->
</g>
</svg>

让我们直接在 HTML 中构建一个带有变换的小型 SVG 图形。

步骤 1:创建一个 SVG 容器。

<svg width="300" height="300" style="border: 1px solid #ccc;">

步骤 2:创建一个 SVG 组(<g>)元素。

<g>

步骤 3:向组中添加一个矩形。

<rect x="20" y="20" width="60" height="30" fill="green"></rect>

步骤 4:向组中添加一个圆形,其位置相对于组的原点。

<circle cx="0" cy="0" r="30" fill="rgba(255,0,0,0.5)"></circle>
<!-- 注意:此示例中,圆形以组的原点为中心 -->

步骤 5:对组元素应用 translate 和 rotate 变换。

<g transform="translate(100, 80) rotate(30)">
<rect x="20" y="20" width="60" height="30" fill="green"></rect>
<circle cx="0" cy="0" r="30" fill="rgba(255,0,0,0.5)"></circle>
</g>
</svg>

完整的 HTML 代码如下:

<!DOCTYPE html>
<html>
<head>
<title>SVG 变换示例</title>
<style> body { font-family: Arial; } </style>
</head>
<body>
<h2>SVG 组变换</h2>
<svg width="300" height="300" style="border: 1px solid #ccc;">
<g transform="translate(100, 80) rotate(30)">
<rect x="20" y="20" width="60" height="30" fill="green"></rect>
<circle cx="0" cy="0" r="30" fill="rgba(255,0,0,0.5)">
</circle>
</g>
</svg>
</body>
</html>

在浏览器中查看时,这将显示一个绿色矩形和一个半透明的红色圆形,它们都相对于 SVG 的左上角移动到 (100,80),然后绕该点旋转 30 度。

D3.js 允许你以编程方式创建和操作这些 SVG 元素及其 transform 属性。

步骤 1:在 HTML 中创建一个容器 div 来放置 SVG。

<div id="svgcontainer"></div>

步骤 2:使用 D3 在容器内创建一个 SVG 图像。

const width = 300;
const height = 300;
const svg = d3.select("#svgcontainer")
.append("svg")
.attr("width", width)
.attr("height", height)
.style("border", "1px solid #ccc");

步骤 3:使用 D3 创建一个 SVG 组元素并设置其 transform 属性。使用模板字面量(template literals)可以使变换字符串更清晰。

const group = svg.append("g")
.attr("transform", `translate(100, 80) rotate(30)`);

步骤 4:创建一个 SVG 矩形并将其添加到组中。

const rect = group.append("rect")
.attr("x", 20)
.attr("y", 20)
.attr("width", 60)
.attr("height", 30)
.attr("fill", "green");

步骤 5:创建一个 SVG 圆形并将其添加到组中。

const circle = group.append("circle")
.attr("cx", 0) // 相对于组的 (0,0)
.attr("cy", 0) // 相对于组的 (0,0)
.attr("r", 30)
.attr("fill", "rgba(255,0,0,0.5)");

集成到 HTML 页面中的完整 D3.js 代码:

<!DOCTYPE html>
<html lang="en">
<head>
<title>D3.js SVG 变换</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style> body { font-family: Arial; } </style>
</head>
<body>
<h2>使用 D3.js 进行 SVG 变换</h2>
<div id="svgcontainer"></div>
<script>
const svgWidth = 300;
const svgHeight = 300;
const svg = d3.select("#svgcontainer")
.append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight)
.style("border", "1px solid #ccc");
const group = svg.append("g")
.attr("transform", `translate(100, 80) rotate(30)`);
const rect = group.append("rect")
.attr("x", 20)
.attr("y", 20)
.attr("width", 60)
.attr("height", 30)
.attr("fill", "green");
const circle = group.append("circle")
.attr("cx", 0) // 相对于组的 (0,0)
.attr("cy", 0) // 相对于组的 (0,0)
.attr("r", 30)
.attr("fill", "rgba(255,0,0,0.5)");
</script>
</body>
</html>

这段 D3 代码实现了与手动编写的 SVG 标记示例相同的视觉效果。此处使用的关键 D3 方法是 .attr("transform", "..."),用于设置变换字符串。理解 SVG 的变换系统对于在 D3 可视化中定位和定向元素至关重要。