You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

创建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);
} 

关键修复点说明

  1. 循环变量作用域:把for(var i=0; i<2; i++)改成for(let i=0; i<2; i++),let会创建块级作用域,确保每次循环的i都是独立的,避免后续回调引用到同一个i值。
  2. 移除重复ID:原来的代码里给多个元素设置了相同的id="fuera"和id="dentro",ID在DOM中必须唯一,所以去掉这些重复的ID,用class来标识元素即可。
  3. 动画回调修正:把each("end", emananting[index])改成each("end", () => emananting(index)),这样每次动画结束后,都会调用对应index的emananting函数,实现无限循环。

这样修改后,多个实例的无限扩散动画就能正常工作了。

内容的提问来源于stack exchange,提问作者yavg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:18:47