Javascript D3如何向堆叠条形图添加圆形上边框

Javascript D3如何向堆叠条形图添加圆形上边框,javascript,d3.js,rounded-corners,Javascript,D3.js,Rounded Corners,我有一个项目,我需要创建一个堆叠条形图。此条形图顶部需要有圆形边框。我找到了一些关于如何绕过条形图上边框的文档。我下面的例子可以在这里找到: 它表示要添加具有以下内容的属性: ` M${x(item.name)},${y(item.value) + ry} a${rx},${ry} 0 0 1 ${rx},${-ry} h${x.bandwidth() - 2 * rx} a${rx},${ry} 0 0 1 ${rx},${ry} v${height - y(item.value)

我有一个项目,我需要创建一个堆叠条形图。此条形图顶部需要有圆形边框。我找到了一些关于如何绕过条形图上边框的文档。我下面的例子可以在这里找到:

它表示要添加具有以下内容的属性:

`
 M${x(item.name)},${y(item.value) + ry}
 a${rx},${ry} 0 0 1 ${rx},${-ry}
 h${x.bandwidth() - 2 * rx}
 a${rx},${ry} 0 0 1 ${rx},${ry}
 v${height - y(item.value) - ry}
 h${-x.bandwidth()}Z
`
您还需要声明定义角锐度的两个变量
rx
ry

我面临的问题是,我无法让它与我的堆叠条形图一起工作。顶部堆栈需要在顶部四舍五入。此外,当顶部堆栈为0时,需要对下一个堆栈进行舍入。因此,无论包含什么数据,条的顶部始终是四舍五入的

我添加了一个精简的片段。它包括一个按钮,用于在其中移除(设置为零)顶部堆栈。当然,这段代码还包括拐弯所需的属性。但它不会变圆

this.width=400;
这个高度=200;
var保证金={
前20名,
右:20,,
底数:30,
左:40
}
该指数=0;
this.svg=d3
.select(“.canvas”)
.classed(“svg容器”,true)
.append(“svg”)
.attr(“类别”、“图表”)
艾特先生(
“查看框”,
`0${this.width}${this.height}`
)
.attr(“保存Aspectratio”、“xMinYMin满足”)
.classed(“svg内容响应”,真)
.附加(“g”);
常量刻度=[01200];
//设定刻度
this.xScale=d3
.scaleBand()
.范围([0,宽度])
.填充(0.3);
this.yScale=d3.scaleLinear().range([this.height,0]);
var bar=this.svg.append(“g”).attr(“class”、“bar”);
常数更新=数据=>{
常量刻度=[01200];
//更新比例。
这个.xScale.domain(data.map(d=>d.key));
这个.yScale.domain([scale[0],scale[1]]);
常量子组=[“家庭”、“工作”、“公共”];
var color=d3
.scaleOrdinal()
.域(子组)
.范围([“206BF3”、“171D2C”、“8B0000”);
var stackData=d3.stack().keys(子组)(数据);
常数rx=12;
常数=12;
//设置转换。
常数dur=1000;
常数t=d3.transition().持续时间(dur);
酒吧
.全选(“g”)
.数据(stackData)
.加入(
回车=>enter
.附加(“g”)
.attr(“填充”,d=>color(d.key)),
null,//没有更新函数
退出=>{
出口
.transition()
.持续时间(dur/2)
.style(“填充不透明度”,0)
.remove();
}
).selectAll(“rect”)
.data(d=>d,d=>d.data.key)
.加入(
回车=>enter
.append(“rect”)
.attr(“类”、“条”)
.attr(“x”,d=>{
返回这个.xScale(d.data.key);
})
.attr(“y”,()=>{
返回此.yScale(0);
})
.attr(“高度”,()=>{
返回this.height-this.yScale(0);
})
.attr(“宽度”,此为.xScale.bandwidth())
艾特先生(
“d”,
项目=>
`M${this.xScale(item.name)},${this.yScale(item.value)+ry}
a${rx},${ry}01${rx},${-ry}
h${this.xScale.bandwidth()-2*rx}
a${rx},${ry}01${rx},${ry}
v${this.height-this.yScale(item.value)-ry}
h${-this.xScale.bandwidth()}Z
`
),
无效的
退出=>{
出口
.transition()
.持续时间(dur/2)
.style(“填充不透明度”,0)
.remove();
}
)
.过渡(t)
.延迟((d,i)=>i*20)
.attr(“x”,d=>this.xScale(d.data.key))
.attr(“y”,d=>{
返回此.yScale(d[1]);
})
.attr(“宽度”,此为.xScale.bandwidth())
.attr(“高度”,d=>{
返回此.yScale(d[0])-此.yScale(d[1]);
});
};
常数数据=[
[{
关键:“1”,
住址:282,
工作:363,
公众电话:379
},
{
键:“2”,
住址:232,
工作:432,
公众:0
}
],
[{
关键:“1”,
住址:282,
工作:363,
公众电话:379
},
{
键:“2”,
住址:232,
工作:0,
公众:0
}
]
];
更新(数据[本索引]);
const swap=document.querySelector(“.swap”);
swap.addEventListener(“单击”,()=>{
如果(this.index<1)this.index+=1;
否则,该指数=0;
更新(数据[本索引]);
});
交换

rect
的图形更改为
path
。因此
.append(“rect”)
变为
.append(“path”)
,您不再需要属性
x
y
高度
宽度

要仅对顶部堆栈进行四舍五入,可以在d3绘制最后一个子组之前将
rx
ry
设置为12(
d[1]-d[0]==d.data[subgroups[subgroups.length-1]]
),在这种情况下为“public”,否则将其设置为0

最后,针对您的最后一个问题:

当顶部堆栈为0时,需要对下一个堆栈进行舍入

堆栈按顺序绘制。在绘制每个堆栈之前,确定下一个堆栈/子组是否为零,如果为零,则将
rx
ry
=12。要了解这一点,您需要获取正在绘制的当前子组,以便确定下一个子组是什么,并获取该子组的值

const current_subgroup = Object.keys(d.data).find(key => d.data[key] === d[1] - d[0]);
const next_subgroup_index = Math.min(subgroups.length - 1, subgroups.indexOf(current_subgroup)+1);
const next_subgroup_data = stackData[next_subgroup_index][i];
            if (next_subgroup_data[1] - next_subgroup_data[0] == 0) { rx = 12; ry = 12; }
this.width=400;
这个高度=200;
var保证金={
前20名,
右:20,,
底数:30,
左:40
}
该指数=0;
this.svg=d3
.select(“.canvas”)
.classed(“svg容器”,true)
.append(“svg”)
.attr(“类别”、“图表”)
艾特先生(
“查看框”,
`0${this.width}${this.height}`
)
.attr(“保存Aspectratio”、“xMinYMin满足”)
.classed(“svg内容响应”,真)
.附加(“g”);
常量刻度=[01200];
//设定刻度
this.xScale=d3
.scaleBand()
.范围([0,宽度])
.填充(0.3);
this.yScale=d3.scaleLinear().range([this.height,0]);
var bar=this.svg.append(“g”).attr(“class”、“bar”);
常数更新=数据=>{
常量刻度=[01200];
//更新比例。
这个.xScale.domain(data.map(d=>d.key));
这个.yScale.domain([scale[0],scale[1]]);
常量子组=[“主”、“w”