让鼠标事件在 d3.js 中始终如一地工作

getting mouse event to work consistently in d3.js

我正在开发一个简单的程序,当单击“工厂”图标时创建圆形节点,然后在单击时删除节点。我的问题是为什么当我 运行 页面加载后的脚本时 d3 selectAll 语句(在 createNode 函数之上)不起作用,尽管当我将相同的语句剪切并粘贴到浏览器控制台。我怀疑这是因为我没有正确链接方法调用,但希望得到一些建议。谢谢。

    var w=5000,h=400,ctr=0; //define bounds of svg

        var ND=[]; //holder of all node data

    var svg = d3.select('body').append('svg') //base svg element
          .attr('width',w)
          .attr('height',h);

    function random(p,q) { return p+Math.floor(Math.random()*(q-p)); }

    var factory=svg.append('circle') //draw the factory widget
        .attr('class','perms') //one of the perm objects
        .attr('cx',50)
        .attr('cy',50)
        .attr('r',30)
        .attr('stroke','black')
        .attr('fill','teal');

    factory.on('click',createNode); //create a new node when factory is clicked

        d3.selectAll('.nodes').on('click',function(e,d){ var did=this.id; console.log(did); 
                            d3.select(this).transition().delay(1000).style('fill','orange').remove();});

    function createNode(x,y) //create a new node and render on screen
    { var r=30; var lx=random(100+r,w-r); var ly=random(0+r,h-r); 
      var rx=svg.append('circle').attr('class','nodes').attr('id',ctr)
        .attr('cx',lx).attr('cy',ly).attr('r',r)
        .attr('stroke','red').attr('fill','yellow');
      var rn={id:ctr++, x:lx, y:ly, r:30, clr:'yellow',lnk:[],ptr:0};
      ND.push(rn);
      return rn;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.0/d3.min.js"></script>

我也尝试了下面的方法,但同样,它只执行 createNode 分支。另一个分支只有在我将完整的函数体粘贴到控制台时才有效。我有一种预感,这可能是因为我没有正确使用输入、更新和退出,但对 d3 的了解还不足以修复它。已经阅读了一些教程和 SO 示例,但仍然卡住了。感谢您的帮助。

d3.selectAll('circle').on('click',function(d)
        { k=d3.select(this); console.log(k.classed('perms')); console.log(k.attr('class')); 
          if (k.classed('perms')) { createNode();}
          if (k.classed('nodes')) { did=this.id; console.log(did);
             for(var i=0;i<ND.length;i++){if (ND[i].id==did){ND.splice(i--,1);}}
             d3.select(this).transition().delay(1000).style('fill','orange').remove();
            }});

My question is why the d3 selectAll statement (above the createNode function) does not work when I run the script after page load, though it all runs fine when I cut and paste that same statement into the browser console.

目前您附加了一个工厂节点,该节点在单击时创建新节点。

然后你 select 所有 现有 圈子 class 节点。此时有none.

然后你可以点击工厂节点,新建一个,但是你不要重新运行 select所有语句。 select所有圈子的离子没有更新,因为之后创建了一个新圈子。

你可以做的是 运行 添加一个节点后再次 selectAll 语句,但是你一次只添加一个节点,而且你已经有一个 select createNode 函数中该节点的离子。所以你可以在这里添加事件监听器:

 function createNode(x,y) { 
    var r=30; var lx=random(100+r,w-r); var ly=random(0+r,h-r); 
    var rx=svg.append('circle')
      .attr('class','nodes')
      ...
      .on(...

     ...
}

    var w=500,h=400,ctr=0; //define bounds of svg

        var ND=[]; //holder of all node data

    var svg = d3.select('body').append('svg') //base svg element
          .attr('width',w)
          .attr('height',h);

    function random(p,q) { return p+Math.floor(Math.random()*(q-p)); }

    var factory=svg.append('circle') //draw the factory widget
        .attr('class','perms') //one of the perm objects
        .attr('cx',50)
        .attr('cy',50)
        .attr('r',30)
        .attr('stroke','black')
        .attr('fill','teal');

    factory.on('click',createNode); //create a new node when factory is clicked


    function createNode(x,y) //create a new node and render on screen
    { var r=30; var lx=random(100+r,w-r); var ly=random(0+r,h-r); 
      var rx=svg.append('circle').attr('class','nodes').attr('id',ctr)
        .attr('cx',lx).attr('cy',ly).attr('r',r)
        .attr('stroke','red').attr('fill','yellow')
        .on('click',function(e,d){ var did=this.id; console.log(did); 
                            d3.select(this).transition().delay(1000).style('fill','orange').remove();});
                            
      var rn={id:ctr++, x:lx, y:ly, r:30, clr:'yellow',lnk:[],ptr:0};
      ND.push(rn);
      return rn;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.0/d3.min.js"></script>

添加圆圈后,select所有代码都在控制台中运行,因为现在有圆圈指向 select - 否则你有一个空的 selection。检查您是否确实 select 任何东西的一种方法是使用 selection.size() 到 return 有多少元素被 select 编辑。