Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用Svg垂直堆叠条形图进行反应(无第三方库)_Javascript_Html_Reactjs_Svg_Charts - Fatal编程技术网

Javascript 使用Svg垂直堆叠条形图进行反应(无第三方库)

Javascript 使用Svg垂直堆叠条形图进行反应(无第三方库),javascript,html,reactjs,svg,charts,Javascript,Html,Reactjs,Svg,Charts,我有下面一段代码。我正在使用React和svg制作条形图。我没有使用任何第三方的图表库。有了下面这段代码,我就能得到条形图了。但问题是我的条形图是水平显示的,我想垂直显示。我不知道如何让这段代码在垂直条形图上工作 export const ReleaseScopeCharts = () => { const data = [ { "name": "Transit", "passed": 2

我有下面一段代码。我正在使用React和svg制作条形图。我没有使用任何第三方的图表库。有了下面这段代码,我就能得到条形图了。但问题是我的条形图是水平显示的,我想垂直显示。我不知道如何让这段代码在垂直条形图上工作


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年是一对一。德国的单曲酒吧和美国的单曲酒吧,像这样?明白了,你想在一个条中显示通过、跳过和失败?实现这一点需要一些时间。我今天休假。这更多的是一个静态数据,没有显示如何使用堆叠图表。你能帮我处理我上面分享的数据吗。