D3.js过渡问题:退出动画期间需触发元素重新进入逻辑
解决D3.js退出动画期间恢复元素时触发Enter式动画的问题
问题分析
当执行元素退出动画(时长5秒)时,DOM元素并未立即被移除,此时点击显示按钮重新绑定数据,这些处于退出过程中的元素会被归入update组而非enter组。但原代码未对update组做任何处理,所以没有任何响应;同时你希望这类场景执行enter式的显示动画,而非用于数据变更的update动画。
解决方案
核心思路是:
- 中断正在进行的退出过渡,避免动画冲突
- 对update组的元素执行与enter组一致的显示动画,模拟enter流程的效果
修改后的完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>D3 Circle Toggle</title> <script src="https://d3js.org/d3.v7.min.js"></script> <style> svg { border: 1px solid #ccc; margin-top: 10px; } button { margin: 5px; } </style> </head> <body> <button id="showBtn">Show Circles</button> <button id="clearBtn">Clear Circles</button></br> <svg width="500" height="200"></svg> <script> const svg = d3.select("svg"); const cx = 50, cy = 100; const data = [80, 120, 60, 150, 200]; function render(data) { // 中断所有圆圈正在进行的过渡,避免动画冲突 svg.selectAll("circle").interrupt(); const circles = svg.selectAll("circle").data(data, (d, i) => i); // Exit: 移除不在数据中的元素 circles.exit() .transition() .duration(5000) .attr("r", 0) .remove(); // Enter: 添加新圆圈并执行显示动画 circles.enter() .append("circle") .attr("cx", (d, i) => cx + i * 80) .attr("cy", cy) .attr("r", 0) .attr("fill", "tomato") .transition() .duration(1000) .attr("r", d => Math.sqrt(d)); // Update: 处理从退出动画中恢复的元素,执行与enter一致的显示动画 circles .attr("r", 0) // 先重置半径为0 .transition() .duration(1000) .attr("r", d => Math.sqrt(d)); } document.getElementById("showBtn").addEventListener("click", () => render(data)); document.getElementById("clearBtn").addEventListener("click", () => render([])); // 初始渲染 render(data); </script> </body> </html>
关键改动说明
- 中断过渡:在
render函数开头调用.interrupt(),强制停止所有圆圈正在进行的退出动画,确保后续动画能立即执行。 - 处理update组:给update组的元素先重置半径为0,再执行和enter组完全相同的显示过渡动画,实现“重新显示”的效果,而非复用数据变更场景的update动画。
内容的提问来源于stack exchange,提问作者rb612
相关产品推荐
相关产品推荐

