为什么selection.exit()。size()为零?

时间:2019-03-09 22:30:51

标签: javascript d3.js

我试图通过将一个空数组连接到d3选择中来从svg中删除rect元素。

不起作用。

想必我误会了一些东西。

下面的代码段设置了svg。当您按下“清除”按钮时,没有任何反应。

我有3个问题(在代码注释中也有注明);

  1. 为什么在联接4个数据项并创建4个关联元素后选择项未报告大小4?
  2. 在clearSVG函数中,为什么在将“ no”数据连接到现有选择之后,exit()的大小为0。
  3. 为什么不移除rect(可能在第二季度得到答复)。

function init(){
    let initialData = [
        {x:0,y:0,c:"black"},
        {x:0,y:90,c:"orange"},
        {x:90,y:0,c:"green"},
        {x:90,y:90,c:"yellow"}        
    ];
    
    let nodes = d3.select("#svg").selectAll("dataNode") ;
            
    //console.log(`empty nodes size: ${nodes.size()}  all good .. ?`);      // reports 0  
    
    nodes    
    .data(initialData)
    .enter()
    .append(`svg:rect`)
    .attr("class", `dataNode`)
    .attr("x", function(d){return d.x;})
    .attr("y", function(d){return d.y;})     
    .attr("width", 10)
    .attr("height", 10)      
    .attr("fill", function(d){return d.c;}) ;
    
    //console.log(`initial data nodes size: ${nodes.size()} - Q1. why is this not 4 ?`); //reports 0
   
};

function clearSVG(){
    let nodes = d3.select("#svg").selectAll(".dataNode"); // all 4 rect elements in the svg
    //console.log(`nodes size: ${nodes.size()}`);// looking good.. 4 nodes reported
    let newData = [] ; // nada, no data 
    nodes.data(newData) ; // join nothing to the rects - no datum for any element in the selection
    //console.log(`exit size: ${nodes.exit().size()} - Q2. Why is this 0 and not 4 ?`);
    nodes.exit().remove();    
    //console.log(`Q3. Why are the rects still present ?`);
};


init();
*{
    border:none;
    padding:0;       
    font-family:Arial;
    box-sizing:border-box;
}
body{
    margin:10px;
}
#svg{
    display: inline-block ;
    width:100px;
    height:100px;

}
#plotBackGround{
    fill: #FBFBFB;  
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg id="svg" viewBox="0 0 100 100" >
   <rect id="plotBackGround" x="0" y="0" width="100" height="100"></rect>
</svg>                           
    
<BR><BR>
       
<button class="btn btn-primary" onclick="clearSVG();">Clear</button>

修改

总结已接受答案的症结所在; selection.data()、. enter()、. append()、. exit()和.remove()返回 new 选择。他们不会 修改被调用的选择,或者返回对其或其部分的引用。

结束编辑

1 个答案:

答案 0 :(得分:3)

问题

这里的问题非常简单:您没有正确的更新选​​择。

让我们看看。您首先要这样做:

let nodes = d3.select("#svg").selectAll(".dataNode");

然后,您更改数据:

let newData = [];
nodes.data(newData);

但是,您没有更改nodes,它们保持原样。以后再做:

nodes.exit().remove();

您实际上只是在这样做:

d3.select("#svg").selectAll(".dataNode").exit().remove();

如您所见,这毫无意义。

解决方案

写正确的更新选​​择。应该是:

nodes = nodes.data(newData);

如果我们替换nodes的值,它将有效地为我们提供:

d3.select("#svg").selectAll(".dataNode").data(newData).exit().remove();

这是仅有更改的代码:

function init(){
    let initialData = [
        {x:0,y:0,c:"black"},
        {x:0,y:90,c:"orange"},
        {x:90,y:0,c:"green"},
        {x:90,y:90,c:"yellow"}        
    ];
    
    let nodes = d3.select("#svg").selectAll("dataNode") ;
            
    //console.log(`empty nodes size: ${nodes.size()}  all good .. ?`);      // reports 0  
    
    nodes    
    .data(initialData)
    .enter()
    .append(`svg:rect`)
    .attr("class", `dataNode`)
    .attr("x", function(d){return d.x;})
    .attr("y", function(d){return d.y;})     
    .attr("width", 10)
    .attr("height", 10)      
    .attr("fill", function(d){return d.c;}) ;
    
    //console.log(`initial data nodes size: ${nodes.size()} - Q1. why is this not 4 ?`); //reports 0
   
};

function clearSVG(){
    let nodes = d3.select("#svg").selectAll(".dataNode"); // all 4 rect elements in the svg
    //console.log(`nodes size: ${nodes.size()}`);// looking good.. 4 nodes reported
    let newData = [] ; // nada, no data 
    nodes = nodes.data(newData) ; // join nothing to the rects - no datum for any element in the selection
    //console.log(`exit size: ${nodes.exit().size()} - Q2. Why is this 0 and not 4 ?`);
    nodes.exit().remove();    
    //console.log(`Q3. Why are the rects still present ?`);
};


init();
*{
    border:none;
    padding:0;       
    font-family:Arial;
    box-sizing:border-box;
}
body{
    margin:10px;
}
#svg{
    display: inline-block ;
    width:100px;
    height:100px;

}
#plotBackGround{
    fill: #FBFBFB;  
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg id="svg" viewBox="0 0 100 100" >
   <rect id="plotBackGround" x="0" y="0" width="100" height="100"></rect>
</svg>                           
    
<BR><BR>
       
<button class="btn btn-primary" onclick="clearSVG();">Clear</button>