D3.js - 动画 (Animation)
D3.js - 创建动画
Section titled “D3.js - 创建动画”D3.js 中的动画主要通过其强大的**过渡(transition)**系统实现。过渡会在指定的时间内平滑地内插元素属性(attributes)和样式(styles),使其从起始状态变化到结束状态。这创造了运动或变化的错觉。虽然 D3 过渡是一种只有两个关键帧(起始和结束)的关键帧动画形式,但它们对于常见的 UI 动画和数据驱动的视觉变化非常灵活。
一个简单的改变背景颜色的动画示例:
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>D3 Animation Example</title> <script src="https://d3js.org/d3.v7.min.js"></script> </head> <body> <h3>Animating with Transitions</h3> <script> d3.select("body") .style("background-color", "white") // Initial state (初始状态) .transition() // Start a transition (启动一个过渡) .duration(2000) // Animation will last 2 seconds (动画将持续 2 秒) .style("background-color", "lightgray"); // Target state (目标状态) </script> </body></html>在这里,文档的背景颜色将在 2 秒内从白色平滑变为浅灰色。
控制动画:duration()
Section titled “控制动画:duration()”duration() 方法设置动画(过渡)的持续时间,单位为毫秒。如果没有指定持续时间,过渡默认为 250ms。
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>D3 Duration Example</title> <script src="https://d3js.org/d3.v7.min.js"></script> </head> <body> <h3>Text Color Animation</h3> <script> d3.select("h3") .transition() .style("color", "green") .duration(5000); // Text color changes to green over 5 seconds (文本颜色在 5 秒内变为绿色) </script> </body></html>您可以使用任何有效的 CSS 颜色格式,包括 RGB:
d3.select("h3") .transition() .style("color", "rgb(0, 150, 120)") // Target color (目标颜色) .duration(5000);D3.js 处理颜色等样式起始值和结束值之间的内插。对于数字属性或样式,它内插数字。对于复杂的值,如颜色或 transform 字符串,D3 使用专门的内插器(interpolators)。
内插(Interpolation)
Section titled “内插(Interpolation)”D3 会根据正在改变的属性或样式自动选择合适的内插器。内插器是一个函数,给定一个通常介于 0(起始)和 1(结束)之间的值 t,它返回一个中间值。您可以通过 d3.interpolate*(a, b) 函数直接访问这些内插器:
d3.interpolateNumber(a, b): 内插两个数字a和b。d3.interpolateRgb(a, b): 内插两种颜色。颜色可以是 CSS 命名颜色或 RGB/HSL 字符串。d3.interpolateString(a, b): 内插两个字符串。它会找到字符串中嵌入的数字并进行内插。- 还有许多其他专门的内插器(例如,用于 transform、数组、对象)。
虽然 D3 通常会自动处理这个问题,但您可以使用 attrTween 或 styleTween 为高级动画创建自定义内插。
延迟动画:delay()
Section titled “延迟动画:delay()”delay() 方法指定过渡开始前的等待时间,单位为毫秒。
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8"> <title>D3 Delay Example</title> <script src="https://d3js.org/d3.v7.min.js"></script> </head> <body> <h3>Font Size Animation with Delay</h3> <script> d3.select("h3") .transition() .delay(2000) // Wait 2 seconds before starting (等待 2 秒后开始) .duration(2000) // Animation lasts 2 seconds (动画持续 2 秒) .style("font-size", "28px"); </script> </body></html>过渡的生命周期
Section titled “过渡的生命周期”了解过渡生命周期有助于协调复杂的动画和交互:
- 已调度 (Scheduled): 当调用
selection.transition()时,过渡被调度。此时,您定义它的最终状态(目标属性/样式)和参数(持续时间、延迟、缓动)。 - 已启动 (Started): 过渡在其指定的
delay之后开始。如果没有延迟,它会尽快开始(通常是几毫秒)。当每个元素的过渡开始时,会分派start事件。 - 正在运行 (Running): 在其
duration期间,过渡根据缓动函数和内插器不断更新元素的属性。每一步实际上将元素从t=0移动到t=1通过内插。 - 已结束 (Ended): 过渡在其开始后经过持续时间后结束。会为每个元素分派
end事件。元素的属性被精确地设置为其目标结束值。
您可以使用 transition.on(eventName, callback) 监听这些生命周期事件:
d3.select("h3") .style("color", "blue") // Initial color (初始颜色) .transition() .delay(500) .duration(1500) .on("start", function() { // 'this' refers to the DOM element (h3 here) (这里的 'this' 指的是 DOM 元素 (即 h3)) // Using a traditional function to preserve 'this' context (使用传统函数以保留 'this' 上下文) d3.select(this).text("Animation Starting!"); }) .style("color", "red") // Target color (目标颜色) .on("end", function() { d3.select(this).text("Animation Ended!").style("color", "green"); });或者,对于选择集中所有过渡完成后执行的操作,Promise 是更简洁的方法:
const myTransition = d3.selectAll(".my-elements") .transition() .duration(1000) .style("opacity", 0);
myTransition.end().then(() => { console.log("All elements have faded out."); // 输出:所有元素都已淡出。 // d3.selectAll(".my-elements").remove(); // For example (例如)});动画是使 D3.js 可视化引人入胜且信息丰富的重要组成部分。