You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不使用第三方库基于SVG实现stacked barchart堆叠柱状图的方法咨询

原生SVG堆叠柱状图调整方案

核心调整点

  • 取消同分类下不同堆叠块的横向偏移:同一分类的所有分段x坐标保持一致,仅不同分类的柱子做横向位置偏移
  • 新增堆叠高度累加逻辑:计算每个分段的y坐标时,需要叠加当前分类下排在它前面的所有分段的总高度,实现纵向层叠效果
  • 统一SVG容器:所有分类的柱子放在同一个SVG内渲染,避免每个分类单独生成SVG导致布局错乱
  • 优化坐标计算逻辑:移除X轴翻转的写法,直接通过y轴坐标正向计算,降低维护成本

修正后可运行代码

const ReleaseScopeCharts = () => {
    const data = [
        {
            name: 'Transit',
            passed: 2,
            skipped: 5,
            failed: 22,
        },
        {
            name: 'Access',
            passed: 7,
            skipped: 2,
            failed: 11,
        },
    ];
    const svgWidth = 500;
    const svgHeight = 500;
    const barWidth = 50;
    const barGap = 80; // 不同柱子之间的间距
    const colors = ['#30D158', '#005EA7', '#FF453A'];
    const categories = ['passed', 'skipped', 'failed'];

    // 计算所有分类的总量最大值,用于高度比例换算
    const maxTotal = Math.max(...data.map(d => categories.reduce((sum, key) => sum + d[key], 0)));

    return (
        <div className="new-card">
            <svg viewBox={`0 0 ${svgWidth} ${svgHeight}`} height={svgHeight} width={svgWidth}>
                {data.map((entry, barIndex) => {
                    // 当前柱子的横向位置
                    const barX = barIndex * barGap;
                    // 累计前面堆叠段的高度
                    let prevHeight = 0;
                    return (
                        <g key={barIndex}>
                            {/* 分类名称展示 */}
                            <text x={barX + barWidth/2} y={svgHeight - 10} textAnchor="middle" fontSize="14">
                                {entry.name}
                            </text>
                            {categories.map((key, segIndex) => {
                                const value = entry[key];
                                if (value <= 0) return null;
                                // 计算当前分段高度,预留40px放底部文字
                                const segHeight = (value / maxTotal) * (svgHeight - 40);
                                // 计算当前分段纵向位置,从下往上堆叠
                                const segY = svgHeight - 40 - prevHeight - segHeight;
                                prevHeight += segHeight;
                                return (
                                    <rect
                                        key={segIndex}
                                        x={barX}
                                        y={segY}
                                        width={barWidth}
                                        height={segHeight}
                                        fill={colors[segIndex]}
                                    />
                                )
                            })}
                        </g>
                    )
                })}
            </svg>
        </div>
    );
};

如果需要实现百分比堆叠柱状图(每个柱子总高度统一为100%),把代码中高度计算的maxTotal替换为当前entry的总数值即可。

内容的提问来源于stack exchange,提问作者Aren Trot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 21:27:03