创建D3.js无限扩散动画多实例时动画消失的问题求助
修复多实例下的无限扩散动画问题
我看了你的代码,问题出在动画循环的回调绑定上,还有一些细节需要调整,下面一步步来解决:
核心问题:动画循环的回调错误
在你的emananting函数里,最后一行的each("end", emananting[index])是错误的:
emananting是一个函数,emananting[index]相当于取函数的第index个属性,这显然不是你想要的,你需要把当前的index绑定到回调里,确保每次循环调用的是对应实例的动画。- 另外,D3的transition结束回调应该传递一个函数,而不是直接执行。
修复后的完整代码
CircleNumber = Math.round(15) const svg = d3.select("body").append("svg").attr("width",250).attr("height",250); const data = Array.from(Array(CircleNumber).keys()); var emanatingCircles=[]; const radialGradient = svg.append("defs") .append("radialGradient") .attr("id", "radial-gradient"); radialGradient.append("stop") .attr("offset", "0%") .attr("stop-color", "#f4425f"); radialGradient.append("stop") .attr("offset", "100%") .attr("stop-color", "orange"); // 把var改成let,避免循环变量的作用域问题 for(let i=0; i<2; i++){ // 移除重复的id,因为id必须唯一,改成用class区分元素 svg.append("circle") .classed('OuterCircle', true) .attr("cx",50*(i+2)) .attr("cy",50*(i+2)) .attr("r",10) .attr("fill","url(#radial-gradient)") .attr("stroke","orange") .on('mouseover',function(){ d3.select(this).transition().ease("bounce").duration(500).attr("r",13) }) .on('mouseout', function(){ d3.select(this).transition().ease("bounce").duration(500).attr("r",10) }); svg.append('circle') .classed('InnerCircle',true) .attr('r',5) .attr('stroke','yellow') .attr('fill','yellow') .attr('opacity',1) .attr('cx',50*(i+2)) .attr('cy',50*(i+2)) .on('mouseover',function(){ d3.select(this).transition().ease("bounce").duration(500).attr("r",7) }) .on('mouseout', function(){ d3.select(this).transition().ease("bounce").duration(500).attr("r",5) }); emanatingCircles[i] = svg .append('circle') .attr('class','emanting') .attr('r',5) .attr('stroke','yellow') .attr('fill','none') .attr('opacity',1) .attr('stroke-width',2) .attr('cx',50*(i+2)) .attr('cy',50*(i+2)) emananting(i); } function emananting(index){ emanatingCircles[index] .transition().duration(5000) .attr('opacity',0) .attr('r',20) .transition().duration(0) .attr('opacity',0) .attr('r',5) // 用箭头函数绑定当前index,确保每次回调调用正确的实例动画 .each("end", () => emananting(index)); emanatingCircles[index].attr("opacity", 1); }
关键修复点说明
- 循环变量作用域:把
for(var i=0; i<2; i++)改成for(let i=0; i<2; i++),let会创建块级作用域,确保每次循环的i都是独立的,避免后续回调引用到同一个i值。 - 移除重复ID:原来的代码里给多个元素设置了相同的
id="fuera"和id="dentro",ID在DOM中必须唯一,所以去掉这些重复的ID,用class来标识元素即可。 - 动画回调修正:把
each("end", emananting[index])改成each("end", () => emananting(index)),这样每次动画结束后,都会调用对应index的emananting函数,实现无限循环。
这样修改后,多个实例的无限扩散动画就能正常工作了。
内容的提问来源于stack exchange,提问作者yavg
相关产品推荐
相关产品推荐

