Javascript 使用Svg垂直堆叠条形图进行反应(无第三方库)
我有下面一段代码。我正在使用React和svg制作条形图。我没有使用任何第三方的图表库。有了下面这段代码,我就能得到条形图了。但问题是我的条形图是水平显示的,我想垂直显示。我不知道如何让这段代码在垂直条形图上工作Javascript 使用Svg垂直堆叠条形图进行反应(无第三方库),javascript,html,reactjs,svg,charts,Javascript,Html,Reactjs,Svg,Charts,我有下面一段代码。我正在使用React和svg制作条形图。我没有使用任何第三方的图表库。有了下面这段代码,我就能得到条形图了。但问题是我的条形图是水平显示的,我想垂直显示。我不知道如何让这段代码在垂直条形图上工作 export const ReleaseScopeCharts = () => { const data = [ { "name": "Transit", "passed": 2
export const ReleaseScopeCharts = () => {
const data = [
{
"name": "Transit",
"passed": 2,
"skipped": 5,
"failed": 22,
},
{
"name": "Access",
"passed": 7,
"skipped": 2,
"failed": 11,
}
]
const fontSize=14
const width=1000
const rowHeight=40
const colors = ["#30D158", "#005EA7", "#FF453A"];
const entries = data.map((d) => ({
name: d.name,
total: d.total,
bars: ["passed", "skipped", "failed"].map((key, i) => ({
value: d[key],
portion: d[key] / 29,
color: colors[i]
}))
.filter((bar) => bar.value)
}))
const heightPerRow = rowHeight;
const canvasHeight = entries.length * heightPerRow;
const canvasWidth = width;
const labelWidth = canvasWidth / 4;
const plotWidth = canvasWidth - labelWidth;
const verticalPadding = heightPerRow / 2;
const barHeight = heightPerRow - verticalPadding;
const horizontalPadding = 0;
const rows = entries.map((entry, i) => {
const widths = entry.bars.map((bar) => plotWidth * bar.portion)
const offsets = entry.bars.map((bar, i, array) => {
const previous = array.slice(0, i);
const offset = previous.map((bar) => bar.portion)
.reduce((a, b) => a + b, 0)
return offset + bar.portion / 2
})
const bars = entry.bars.map((bar, i) => {
const barWidth = widths[i] - horizontalPadding;
return (<g key={i} transform={`translate(${plotWidth * offsets[i]}, ${heightPerRow / 2})`}>
<rect
rx={barHeight / 2} ry={barHeight / 2} width={barWidth} height={barHeight} fill={bar.color} x={-barWidth / 2} y={-barHeight / 2} />
<text fill={"#fff"} fontSize={fontSize} textAnchor={"middle"} alignmentBaseline={"middle"}>{bar.value}</text>
</g>)
})
return (
<g key={i} transform={`translate(${labelWidth},${heightPerRow * i})`}>
<g transform={`translate(${-labelWidth}, ${heightPerRow / 2})`}>
<text
fontSize={fontSize}
textAnchor={"start"}
alignmentBaseline={"middle"}>{entry.name}</text>
</g>
{bars}
</g>
)
})
return (
<div className="new-card">
<div>
</div>
<svg viewBox={`0, 0, ${canvasWidth}, ${canvasHeight}`}
height={canvasHeight}
width={canvasWidth}
>
{rows}
</svg>
</div>
)}
我在网上看了一个视频
这家伙能垂直完成条形图。我不确定我在展示它时哪里出错了。我所做或尝试的任何更改都会显示水平条形图
export const ReleaseScopeCharts = () => {
const data = [
{
"name": "Transit",
"passed": 2,
"skipped": 5,
"failed": 22,
},
{
"name": "Access",
"passed": 7,
"skipped": 2,
"failed": 11,
}
]
const fontSize=14
const width=1000
const rowHeight=40
const colors = ["#30D158", "#005EA7", "#FF453A"];
const entries = data.map((d) => ({
name: d.name,
total: d.total,
bars: ["passed", "skipped", "failed"].map((key, i) => ({
value: d[key],
portion: d[key] / 29,
color: colors[i]
}))
.filter((bar) => bar.value)
}))
const heightPerRow = rowHeight;
const canvasHeight = entries.length * heightPerRow;
const canvasWidth = width;
const labelWidth = canvasWidth / 4;
const plotWidth = canvasWidth - labelWidth;
const verticalPadding = heightPerRow / 2;
const barHeight = heightPerRow - verticalPadding;
const horizontalPadding = 0;
const rows = entries.map((entry, i) => {
const widths = entry.bars.map((bar) => plotWidth * bar.portion)
const offsets = entry.bars.map((bar, i, array) => {
const previous = array.slice(0, i);
const offset = previous.map((bar) => bar.portion)
.reduce((a, b) => a + b, 0)
return offset + bar.portion / 2
})
const bars = entry.bars.map((bar, i) => {
const barWidth = widths[i] - horizontalPadding;
return (<g key={i} transform={`translate(${plotWidth * offsets[i]}, ${heightPerRow / 2})`}>
<rect
rx={barHeight / 2} ry={barHeight / 2} width={barWidth} height={barHeight} fill={bar.color} x={-barWidth / 2} y={-barHeight / 2} />
<text fill={"#fff"} fontSize={fontSize} textAnchor={"middle"} alignmentBaseline={"middle"}>{bar.value}</text>
</g>)
})
return (
<g key={i} transform={`translate(${labelWidth},${heightPerRow * i})`}>
<g transform={`translate(${-labelWidth}, ${heightPerRow / 2})`}>
<text
fontSize={fontSize}
textAnchor={"start"}
alignmentBaseline={"middle"}>{entry.name}</text>
</g>
{bars}
</g>
)
})
return (
<div className="new-card">
<div>
</div>
<svg viewBox={`0, 0, ${canvasWidth}, ${canvasHeight}`}
height={canvasHeight}
width={canvasWidth}
>
{rows}
</svg>
</div>
)}
export const ReleaseScopeCharts=()=>{
常数数据=[
{
“名称”:“运输”,
"通过":二,,
“跳过”:5,
“失败”:22,
},
{
“名称”:“访问”,
“通过”:7,
“跳过”:2,
“失败”:11,
}
]
常数fontSize=14
常数宽度=1000
常数行高=40
常量颜色=[“30D158”、“005EA7”、“FF453A”];
const entries=data.map((d)=>({
姓名:d.name,
总计:d.total,
条形图:[“通过”、“跳过”、“失败”].map((键,i)=>({
值:d[键],
部分:d[键]/29,
颜色:颜色[i]
}))
.filter((条)=>条值)
}))
const heightPerRow=行高;
const canvasHeight=entries.length*heightPerRow;
常量画布宽度=宽度;
常量标签宽度=画布宽度/4;
const plotWidth=画布宽度-标签宽度;
常量垂直填充=高度Perrow/2;
常数barHeight=heightPerRow-垂直填充;
常量水平填充=0;
const rows=entries.map((entry,i)=>{
常量宽度=entry.bar.map((bar)=>plotWidth*bar.partment)
常量偏移量=entry.bar.map((bar,i,数组)=>{
const previous=array.slice(0,i);
常量偏移=上一个.map((条形)=>条形部分)
.减少((a,b)=>a+b,0)
返回偏移量+条形部分/2
})
常量条=entry.bar.map((条,i)=>{
const barWidth=宽度[i]-水平填充;
返回(
{bar.value}
)
})
返回(
{entry.name}
{bar}
)
})
返回(
{rows}
)}
谁能帮我找出哪里出了问题。我刚刚帮你弄明白了。你可以做剩下的计算
export const ReleaseScopeCharts = () => {
const data = [
{
name: 'Transit',
passed: 2,
skipped: 5,
failed: 22,
},
{
name: 'Access',
passed: 7,
skipped: 2,
failed: 11,
},
];
const width = 500;
const colors = ['#30D158', '#005EA7', '#FF453A'];
const entries = data.map((d) => ({
name: d.name,
total: ['passed', 'skipped', 'failed'].reduce((acc, key) => acc + d[key], 0),
bars: ['passed', 'skipped', 'failed'].map((key, i) => ({
value: d[key],
color: colors[i],
}))
.filter((bar) => bar.value),
}));
const rows = (entry) => entry.bars.map((bar, index) => {
const height = (bar.value / entry.total) * 100;
return (
<g key={index}>
<rect
width={50}
height={`${height}%`}
fill={bar.color}
x={index * 60} // multiply with the width (50) + 10 for space
/>
</g>
);
});
return (
<div className="new-card">
<div />
{entries.map((entry) => (
<>
{entry.name}
<svg viewBox={`0, 0, ${width}, ${500}`}
height={500}
width={width}
style={{ transform: `rotateX(180deg)` }}
>
{rows(entry)}
</svg>
</>
))}
</div>
);
};
export const ReleaseScopeCharts=()=>{
常数数据=[
{
名称:'运输',
通过:2,,
跳过:5,
失败:22,
},
{
名称:'访问',
通过日期:7,,
跳过:2,
失败:11,
},
];
常数宽度=500;
常量颜色=['#30D158'、'#005EA7'、'#FF453A';
const entries=data.map((d)=>({
姓名:d.name,
总计:[“通过”、“跳过”、“失败”].reduce((acc,键)=>acc+d[键],0),
条形图:[“通过”、“跳过”、“失败”].map((键,i)=>({
值:d[键],
颜色:颜色[i],
}))
.过滤器((条形)=>条形值),
}));
常量行=(条目)=>entry.bar.map((条,索引)=>{
常量高度=(bar.value/条目总数)*100;
返回(
);
});
返回(
{entries.map((entry)=>(
{entry.name}
{行(条目)}
))}
);
};
我将稍微断章取义,以显示条形图结果-可以在SVG中添加更多的“条形图”,这将留给您
注意重要的部分是
,其中宽度和高度显示条的“大小”
为了好玩,我在CSS上添加了一些鼠标
.bar{
填料:石灰;
/*改变背景*/
高度:10雷姆;
过渡:填充。3s轻松;
光标:指针;
字体系列:Helvetica,无衬线;
}
.bar文本{
颜色:黑色;
字体大小:0.75rem;
}
.bar:悬停,
.酒吧:焦点{
填充:蓝色;
}
.bar:悬停文本,
.bar:焦点文本{
填充物:红色;
}
单柱状图
欢乐日
乐趣
山羊
您应该有一个固定的宽度,高度应该是您的计算值。你做的恰恰相反。此外,您还需要在%的基础上设置高度,并为不同的图表呈现不同的svg。@Yadab可能是正确的。我试图翻转这些值,但没有得到xP的任何结果。不管怎么说,我玩了一个小游戏,得到了一个垂直的图表-不一样,它的WIP很高,但它是垂直的->。也许会有所帮助或提供一些想法,不幸的是我今天不能继续,这是一个有趣的“任务”@Yadab-如果可以,请分享一个工作示例谢谢@Yadab。以上代码提供了分组垂直条形图。你能指出堆叠条形图应该做的更改吗?你想要这样的东西吗@亚达布-没有。。事实上,在tat的例子中,2010年和2011年在德国和美国是并排排列的。我希望2010年和2011年是一对一。德国的单曲酒吧和美国的单曲酒吧,像这样?明白了,你想在一个条中显示通过、跳过和失败?实现这一点需要一些时间。我今天休假。这更多的是一个静态数据,没有显示如何使用堆叠图表。你能帮我处理我上面分享的数据吗。