Skip to content

D3.js - 缩放 API

缩放 (Zooming) 和平移 (panning) 是探索详细可视化图形的关键交互方式。D3 的 Zoom API (d3-zoom) 提供了一种强大的方法来实现这些行为,通常通过鼠标滚轮、拖动或触摸手势。本章将介绍如何配置和使用 Zooming API。

您可以通过包含完整的 D3 库或独立的 d3-zoom 模块来使用 Zoom API。d3-zoom 模块处理复杂的事件管理,以实现平滑的缩放和平移。

<!-- 选项 1: 包含完整的 D3 库 -->
<script src="https://d3js.org/d3.v7.min.js"></script>
<!-- 选项 2: 包含独立的 d3-zoom 模块 -->
<!-- 注意: d3-zoom 依赖于 d3-dispatch, d3-drag, d3-interpolate, d3-selection, d3-transition -->
<!-- 为简单起见,完整的 D3 包通常对初学者更友好。 -->
<!-- <script src="https://d3js.org/d3-zoom.v2.min.js"></script> -->
<script>
// 示例初始化
// const zoom = d3.zoom();
// d3.select("svg").call(zoom);
</script>

缩放行为通过监听选定的 SVG 元素上的输入事件 (如鼠标滚轮、拖动) 来工作。当这些事件发生时,D3 会计算一个 ‘zoom transform’ (缩放变换)。这个变换 (包括 x, y 坐标平移和 k 缩放因子) 随后应用于您想要缩放/平移的内容。

缩放交互的关键元素:

  1. 缩放行为 (Zoom Behavior): 使用 d3.zoom() 创建。
  2. 目标元素 (Target Element): 一个 SVG 元素 (通常是 <svg> 或 <g> 元素),它监听缩放手势。您使用 selection.call(zoom) 将缩放行为应用于此元素。
  3. 缩放事件 (Zoom Event): 缩放行为会分派 zoom 事件。您的监听器 (listener) 函数会接收一个 event 对象,其中 event.transform 包含当前的缩放变换 (zoom transform)。
  4. 应用变换 (Applying the Transform): 在缩放事件监听器内部,您将 event.transform 应用于您想要缩放和平移的元素。这通常通过设置包含可视化元素的 SVG 组 (<g>) 元素的 transform 属性来完成。

以下是 D3 Zoom API 中一些最常用的方法:

  • d3.zoom() − 创建一个新的缩放行为 (zoom behavior)。
  • zoom(selection) − 将缩放行为应用于给定的 selection。这通常通过 selection.call(zoom) 完成。
  • zoom.transform(selection, transform[, point]) − 以编程方式将选中元素的当前缩放变换 (zoom transform) 设置为指定的 transform。可选的 point 可以指定缩放原点 (zoom origin)。
  • zoom.translateBy(selection, x, y) − 将选中元素的当前缩放变换在屏幕坐标系下平移 x 和 y。
  • zoom.translateTo(selection, x, y[, point]) − 平移选中元素的当前缩放变换,使得给定的 point (数据坐标) 显示在指定的 x, y 位置 (屏幕坐标)。
  • zoom.scaleBy(selection, k[, point]) − 将选中元素的当前缩放变换按 k (乘数) 进行缩放,可选地围绕指定的 point (屏幕坐标) 进行。
  • zoom.scaleTo(selection, k[, point]) − 将选中元素的当前缩放变换缩放至绝对比例因子 (absolute scale factor) k,可选地围绕指定的 point (屏幕坐标) 进行。
  • zoom.filter([filterFunction]) − 设置一个过滤函数 (filter function) 来控制哪些输入事件触发缩放手势。默认过滤器会忽略鼠标右键或按下 Alt 等修饰键时的缩放。
  • zoom.wheelDelta([deltaFunction]) − 自定义鼠标滚轮事件如何转换为缩放。默认值是 (event) => -event.deltaY * (event.deltaMode === 1 ? 0.05 : event.deltaMode ? 1 : 0.002) * (event.ctrlKey ? 10 : 1)。
  • zoom.extent([[x0, y0], [x1, y1]]) − 设置视口范围 (viewport extent)。默认为所属 SVG 元素的尺寸。
  • zoom.scaleExtent([minScale, maxScale]) − 设置允许的最小和最大比例因子 (scale factors) (例如,[0.5, 8])。
  • zoom.translateExtent([[x0, y0], [x1, y1]]) − 设置可平移范围 (pannable extent)。考虑到当前比例,防止平移超出这些边界。
  • zoom.clickDistance([distance]) − 设置鼠标在 mousedown 和 mouseup 事件之间移动的最大距离,以便识别为 click 事件。
  • zoom.duration([duration]) − 设置双击 (放大) 和编程调用缩放时触发的缩放过渡 (zoom transitions) 的持续时间 (以毫秒为单位)。默认值为 250ms。
  • zoom.interpolate([interpolateFactory]) − 为缩放过渡设置插值工厂 (interpolation factory)。默认值为 d3.interpolateZoom。
  • zoom.on(typenames[, listener]) − 为缩放事件附加一个事件监听器 (event listener)。常见的 typenames 包括 start (缩放手势开始)、zoom (变换变化) 和 end (缩放手势结束)。

示例:在 SVG 元素上进行基本缩放

Section titled “示例:在 SVG 元素上进行基本缩放”

让我们创建一个简单的示例,以便我们可以在一组 SVG 圆形上进行缩放和平移。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>D3.js Zoom Example</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
svg {
border: 1px solid #ccc;
cursor: grab;
}
.zoomed-content circle {
fill: steelblue;
}
</style>
</head>
<body>
<svg width="600" height="400">
<g class="zoomed-content">
<circle cx="100" cy="100" r="40"></circle>
<circle cx="250" cy="150" r="30"></circle>
<circle cx="400" cy="200" r="50"></circle>
</g>
</svg>
<script>
const svg = d3.select("svg");
const g = svg.select(".zoomed-content");
// 创建缩放行为
const zoom = d3.zoom()
.scaleExtent([0.5, 5]) // 最小和最大缩放级别
.on("zoom", (event) => {
// event.transform 包含当前变换 (k, x, y)
g.attr("transform", event.transform);
});
// 将缩放行为应用于 SVG 元素
svg.call(zoom);
// 可选:设置初始变换
// svg.call(zoom.transform, d3.zoomIdentity.translate(50, 50).scale(1.2));
</script>
</body>
</html>

在此示例中,鼠标拖动将平移圆形,鼠标滚轮将放大或缩小。来自 ‘zoom’ 事件的 event.transform 对象直接应用于包含圆形的 <g> 元素。

  • 事件处理 (Event Handling): 现代 D3 将 event 对象作为第一个参数传递给监听器 (listeners)。d3.event 已被弃用。通过 event.transform 访问缩放变换 (zoom transform)。
  • 变换应用 (Transform Application): 将缩放变换 (zoom transform) 应用于容器 <g> 元素,而不是单独的形状,以获得更好的性能和更易于管理。
  • 坐标系统 (Coordinate Systems): 注意区分屏幕坐标 (screen coordinates) 和数据坐标 (data coordinates),尤其是在使用 translateTo 或 scaleTo 等方法并带有 point 参数时。
  • 与坐标轴的交互 (Interaction with Axes): 当缩放带有坐标轴 (axes) 的图表时,您需要在缩放事件处理程序 (zoom event handler) 中更新坐标轴比例尺 (axis scales) 并重新渲染坐标轴。请参阅比例尺 (scales) 上的 rescaleX / rescaleY 方法。

对于更高级的缩放场景,例如编程缩放 (programmatic zooming) 或与其他交互的集成,请查阅 d3-zoom 官方文档。