【发布时间】:2021-07-20 10:09:06
【问题描述】:
我有以下代码。我将 React 和 svg 用于条形图。我没有使用任何第三方库来制作图表。使用下面的这段代码,我可以获得条形图。但问题是我的条形图水平显示,我想垂直显示。我无法弄清楚如何让同一段代码用于垂直条形图。
我在网上看到一个视频https://egghead.io/lessons/javascript-build-a-bar-chart-with-svg-from-scratch-with-react 这家伙能够垂直实现条形图。我不确定我在显示它时哪里出错了。我所做或尝试的任何更改,它总是显示水平条形图。
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>
)}
谁能帮我弄清楚我哪里出错了。
【问题讨论】:
-
你应该有一个固定的宽度和高度应该是你的计算。你做的完全相反。此外,您还需要基于 % 的高度并为不同的图表呈现不同的 svg。
-
@Yadab 可能是对的。我试图翻转这些值,但 xP 一无所获。无论如何,我玩了一点,得到了一个垂直的图表——不一样,它非常 WIP,但它是垂直的 -> codesandbox.io/s/… 。也许会有所帮助或提供一些想法,不幸的是我今天不能继续,这是一个有趣的“任务”
-
@Yadab - 如果可以,请分享一个工作示例
标签: javascript html reactjs svg charts