Skip to content

D3.js - 过渡效果 API

D3.js 过渡(transitions)允许选定的元素随时间平滑地、动画地变化。d3-transition 模块提供了核心功能。当您应用过渡时,D3 会将属性(attributes)和样式(styles)从当前值内插(interpolate)到目标值,从而创建动画。

d3-transition 模块是主 D3.js 库的一部分。请确保您的 HTML 中包含了 D3.js:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>D3.js Transitions API Example</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
.shape { width: 50px; height: 50px; background-color: steelblue; margin: 10px; }
</style>
</head>
<body>
<div class="shape"></div>
<script>
// Your D3.js transition code will go here
</script>
</body>
</html>

用于启动和管理过渡的关键方法:

  • selection.transition([name]): 在选定的元素上启动一个过渡。可选的 name 参数允许在同一元素上进行多个命名过渡,防止它们相互干扰。如果未指定名称,则为未命名过渡。
  • selection.interrupt([name]): 立即停止选定元素上指定 name 的活动过渡(如果未指定名称,则停止所有未命名过渡)。这对于应覆盖正在进行动画的用户交互非常有用。
  • d3.interrupt(node[, name]): 中断单个 DOM node 上指定 name 的过渡。
  • d3.transition([name]): 创建一个具有指定 name 的新过渡配置。这可用于定义共享的过渡参数,尽管对于更简单的情况,直接在 selection.transition() 上进行链式调用更常见。

一旦过渡启动,您可以使用熟悉的 D3 选择集方法。当这些方法在过渡上调用时,它们将应用于正在过渡中的元素,或定义过渡的最终状态。

  • transition.select(selector): 对于每个选定的元素,选择第一个与其匹配的后代元素(descendant element)。返回的过渡应用于这些后代元素。
  • 示例: d3.selectAll("g").transition().select("rect").attr("fill", "red"); 会过渡正在过渡的组中矩形的填充颜色。
  • transition.selectAll(selector): 类似于 select,但选择所有匹配的后代元素。
  • transition.filter(filter): 过滤过渡中的选择集,返回一个新过渡,仅包含 filter(函数或选择器字符串)为 true 的元素。
  • transition.merge(otherTransition): 将此过渡与另一个 otherTransition 合并。当处理 enter/update 选择集时很有用,其中新元素也需要过渡。
  • transition.transition(): 调度一个新的过渡,使其在当前元素上的过渡结束后开始。这是一种强大的链式顺序动画的方法。除非被覆盖,新过渡会继承父过渡的属性,如持续时间(duration)和缓动(easing)。

链式过渡的示例:

d3.select(".shape")
.transition() // First transition (第一个过渡)
.duration(1000)
.style("background-color", "orange")
.transition() // Second transition, starts after the first one ends (第二个过渡,在第一个结束后开始)
.duration(1000)
.style("transform", "translateX(100px)")
.transition() // Third transition (第三个过渡)
.delay(500) // Starts 500ms after the second one ends (在第二个结束后 500 毫秒开始)
.duration(1000)
.style("background-color", "steelblue")
.style("transform", "translateX(0px)");

这将按顺序动画化一个形状的颜色,然后是位置,然后是颜色和位置回到原位。

  • d3.active(node[, name]): 返回给定 node 上指定 name 的活动过渡(如果存在)。对于检查元素当前是否正在过渡非常有用。

控制动画的时间和感觉:

  • transition.delay([value]): 设置过渡延迟,单位为毫秒。如果 value 是一个函数,它会为每个选定的元素评估(传入 datum, index, nodes),并应返回延迟时间。如果未指定 value,则返回第一个非空元素的当前延迟。
  • 示例: transition.delay((d, i) => i * 100); // Staggered start (交错启动)
  • transition.duration([value]): 设置过渡持续时间,单位为毫秒。与 delay 类似,value 可以是常数或函数。默认值为 250ms。
  • transition.ease([easingFunction]): 设置缓动函数(easing function),它控制变化率随时间的变化(例如,慢启动、快结束)。D3 在 d3-ease 中提供了许多内置缓动函数(例如,d3.easeLinear, d3.easeCubicInOut, d3.easeBounce)。如果未提供函数,则返回当前的缓动函数。

过渡会触发事件并返回 Promise,从而实现更复杂的编排:

  • transition.on(typenames, listener): 为 start、end 或 interrupt 事件添加事件监听器。当事件发生在元素上时,将调用 listener 函数。其 this 上下文是 DOM 元素。
  • transition.end(): 返回一个 Promise,该 Promise 在选择集中的所有过渡都结束后解析。这对于在动画完成后运行代码非常有用,无需复杂的事件跟踪。示例:myTransition.end().then(() => console.log("Transition finished!"));

这个 API 提供了创建复杂动画的强大方法。在下一章中,我们将讨论 D3.js 中的拖放概念。