如何在D3.js中为不同元素实现链式顺序过渡?
实现D3元素的链式过渡(按顺序触发,独立时长)
嘿,我懂你想要的效果——让不同元素的过渡按顺序执行,第一个元素的过渡全部完成后再启动第二个,而且每个过渡还能设置不一样的时长,不想用那种手动累加延迟的麻烦办法对吧?你的尝试思路是对的,但D3其实有更优雅准确的方式来实现这个需求,不用靠计算时间总和~
问题分析
你原来的代码里用了transition.each(),但这个方法是立即执行的,不会等待前一个过渡完成,所以三个元素的过渡会同时启动,达不到链式的效果。下面给你两种靠谱的实现方式:
方法1:利用过渡的"end"事件(推荐,灵活度高)
这种方式是监听前一个元素的过渡完成事件,触发下一个元素的过渡,每个元素的过渡时长完全独立,不需要手动计算时间:
<!DOCTYPE html> <meta charset="utf-8"> <head> <script src="https://d3js.org/d3.v4.js"></script> </head> <body> <script> let sel = d3.select("body") let selFirst = sel.append("h1").attr("class", "first").text("first"); let selSecond = sel.append("h2").attr("class", "second").text("second"); let selThird = sel.append("h3").attr("class", "third").text("third"); // 定义每个元素的过渡函数 function animateFirst() { selFirst.transition() .duration(1000) // 第一个过渡(变透明)的时长 .style("opacity", 0) .transition() // 链式内部过渡(变回不透明) .duration(800) .style("opacity", 1) .on("end", animateSecond); // 过渡全部完成后,触发第二个元素的动画 } function animateSecond() { selSecond.transition() .duration(600) .style("opacity", 0) .transition() .duration(900) .style("opacity", 1) .on("end", animateThird); } function animateThird() { selThird.transition() .duration(700) .style("opacity", 0) .transition() .duration(1100) .style("opacity", 1); } // 启动第一个动画 animateFirst(); </script> </body> </html>
这种方式的好处是每个元素的过渡逻辑可以单独编写,时长想设多少就设多少,完全不用管其他元素的时间,D3会自动监听过渡结束的时机,精准触发下一个动画。
方法2:利用D3的过渡序列
如果你想把整个链式逻辑写在一起,可以用transition().transition()来创建一个全局的过渡序列,每个后续过渡会在前一个完成后启动:
<!DOCTYPE html> <meta charset="utf-8"> <head> <script src="https://d3js.org/d3.v4.js"></script> </head> <body> <script> let sel = d3.select("body") let selFirst = sel.append("h1").attr("class", "first").text("first"); let selSecond = sel.append("h2").attr("class", "second").text("second"); let selThird = sel.append("h3").attr("class", "third").text("third"); // 创建过渡序列 d3.transition() // 第一个阶段:执行第一个元素的过渡 .on("start", function() { selFirst.transition(this) .duration(1000) .style("opacity", 0) .transition() .duration(800) .style("opacity", 1); }) // 等待前一个阶段完成,进入第二个阶段 .transition() .on("start", function() { selSecond.transition(this) .duration(600) .style("opacity", 0) .transition() .duration(900) .style("opacity", 1); }) // 等待第二个阶段完成,进入第三个阶段 .transition() .on("start", function() { selThird.transition(this) .duration(700) .style("opacity", 0) .transition() .duration(1100) .style("opacity", 1); }); </script> </body> </html>
这里的this会指向当前的过渡对象,让元素的过渡继承全局序列的时序,确保按顺序执行。
内容的提问来源于stack exchange,提问作者ee2Dev
相关产品推荐
相关产品推荐

