D3.js d3 selection.exit().remove()不工作,_exit始终为数组(0)

D3.js d3 selection.exit().remove()不工作,_exit始终为数组(0),d3.js,D3.js,我已经通过了不少教程,但仍然无法解决如何正确更新数据,任何帮助将不胜感激,谢谢 由于某些原因,代码在代码段中运行不正常,我对使用它很陌生, 我想要实现的是,通过单击按钮,数据得到更新,我尝试使用selection.exit().remove,但是exit数组总是空的,我真的不明白它是如何工作的 const arr=[{ 名称:“A”, 数据集_1:5, 数据集2:6, }, { 名称:“B”, 数据集_1:7, 数据集2:22, }, { 名称:“C”, 数据集_1:33, 数据集2:23,

我已经通过了不少教程,但仍然无法解决如何正确更新数据,任何帮助将不胜感激,谢谢

由于某些原因,代码在代码段中运行不正常,我对使用它很陌生, 我想要实现的是,通过单击按钮,数据得到更新,我尝试使用selection.exit().remove,但是exit数组总是空的,我真的不明白它是如何工作的

const arr=[{
名称:“A”,
数据集_1:5,
数据集2:6,
},
{
名称:“B”,
数据集_1:7,
数据集2:22,
},
{
名称:“C”,
数据集_1:33,
数据集2:23,
},
{
名称:“D”,
数据集_1:20,
数据集2:12,
},
{
名称:“E”,
数据集_1:21,
数据集2:15,
},
{
名称:“F”,
数据集_1:15,
数据集2:18,
},
];
//用于添加数据集的函数
设计数器=2;
常量添加集=(arr)=>{
const ran=()=>Math.floor(Math.random()*20+1);
常量添加=(arr)=>{
计数器++;
arr.map((i)=>(i[`dataset_${counter}`]=ran());
};
添加(arr);
};
//用于删除数据集的函数
常量删除集=(arr)=>{
arr.map((i)=>delete i[`dataset_${counter}`];
计数器>=1?计数器--:计数器;
};
//绘制面积图
常量绘图=()=>{
//1号定义要绘制的位置
让svg=d3.选择(“svg”),
保证金={
左:50,,
右:50,,
前15名,
底数:30
},
宽度=+svg.attr(“宽度”)-margin.left-margin.right,
高度=+svg.attr(“高度”)-margin.top-margin.bottom,
g=svg
.附加(“g”)
艾特先生(
“转化”,
翻译(“+margin.left+”,“+margin.top+”)
);
//第2组轴
让categoriesNames=arr.map((d)=>d.name);
让xScale=d3.scalePoint().domain(categoriesNames).range([0,width]);//scalePoint使轴以与scaleBand相比的值开始
让copy=JSON.parse(JSON.stringify(arr));
copy.map((i)=>删除i.name);
var yScale=d3
.scaleLinear()
.范围([高度,0])
.domain([0,d3.max(copy,(i)=>Math.max(…Object.values(i))))];
设colorScale=d3.scaleOrdinal().range(d3.schemeSet3);
让dataset=Object.keys(arr[0]).filter((i)=>i!=“name”);
域(数据集);
g、 附加(“g”)
.attr(“类”、“x轴”)
.attr(“变换”、“平移(0)”、“高度+”)
.call(d3.axisBottom(xScale));
g、 追加(“g”).attr(“class”,“y轴”).call(d3.axisLeft(yScale));
g、 退出().remove();
//三号绘图图
让areaData=数据集.map((i)=>{
返回{
id:我,
值:arr.map((d)=>{
返回{
姓名:d.name,
价值:d[i]
};
}),
};
});
设发电机=d3
1.区域()
.curve(d3.curveMonotoneX)
.y0(yScale(0))
.x((d)=>xScale(d.name))
.y1((d)=>yScale(d.value));
设面积=g
.selectAll(“.area”)
.数据(区域数据)
.输入()
.附加(“g”)
.attr(“类”,(d)=>`area${d.id}`);
area.exit().remove();
地区
.append(“路径”)
.attr(“d”,(d)=>{
返回发生器(d值);
})
.attr(“不透明度”,0.6)
.样式(“填充”(d)=>颜色刻度(d.id));
};
//钮扣
draw();
常数更新=()=>{
添加_集(arr);
draw();
};
常量删除=()=>{
移除_组(arr);
draw();
};
d3.选择(“主体”)
.append(“按钮”)
.text(“删除数据集”)
。打开(“单击”,删除);
d3.选择(“主体”)
.append(“按钮”)
.text(“添加数据集”)
。打开(“单击”,更新)

selection.exit()
为空,因为
selection
g
中节点的子集,并且每次调用
draw
时都会新添加
g
。您需要将一次性逻辑(绘制轴、附加容器元素、设置高度/宽度等)与每次要运行的逻辑分开

您还应该在代码中看到其中一个区域的颜色发生了变化。那是因为在它前面画了另一个区域。如果真的出了问题,它会重新调整现有区域的用途,并且无法删除您不需要的区域。这是一个指针,您可以在第二次追加不应该追加的内容

但还有更多。您可以使用
g.selectAll(“.area”)
,附加
g
元素,但不给它类
area
。相反,您给它类
areadataset_1
areadataset_2
。这样,在随后的调用中,您将找不到区域元素

您还需要了解
.merge()
。我建议你查一些教程,比如。您只更新了新路径,从未更新过旧路径。因为您不需要
g
,所以我现在删除了它,使其余的逻辑更简单

const arr=[{
名称:“A”,
数据集_1:5,
数据集2:6,
},
{
名称:“B”,
数据集_1:7,
数据集2:22,
},
{
名称:“C”,
数据集_1:33,
数据集2:23,
},
{
名称:“D”,
数据集_1:20,
数据集2:12,
},
{
名称:“E”,
数据集_1:21,
数据集2:15,
},
{
名称:“F”,
数据集_1:15,
数据集2:18,
},
];
//用于添加数据集的函数
设计数器=2;
常量添加集=(arr)=>{
const ran=()=>Math.floor(Math.random()*20+1);
常量添加=(arr)=>{
计数器++;
arr.map((i)=>(i[`dataset_${counter}`]=ran());
};
添加(arr);
};
//用于删除数据集的函数
常量删除集=(arr)=>{
arr.map((i)=>delete i[`dataset_${counter}`];
计数器>=1?计数器--:计数器;
};
常量边距={
左:50,,
右:50,,
前15名,
底数:30
};
让我们,
宽度,
高度,
G
常量设置=()=>{
//1号定义要绘制的位置
svg=d3。选择(“svg”);
宽度=+svg.attr(“宽度”)-margin.left-margin.right;
高度=+svg.attr(“高度”)-margin.top-margin.bottom;
g=svg
.附加(“g”)
艾特先生(
“转化”,
翻译(“+margin.left+”,“+margin.top+”)
);
}
//绘制面积图
C