Chart.js - 多个数据集的 0 值对齐

问题描述 投票:0回答:1

我正在尝试比较 Chart.js 中的 2 个数据集。值之间存在很大差异,因此为了比较这些值,我们决定在 2 个不同的 y 轴上绘制数据图表。

1 个数据集有一些负值,并且图表的基础从负值开始。 另一个数据集只有正值,并且图表的基数从 0 开始。

是否有任何设置允许我在 y 轴上对齐 0(当使用 2 个不同的轴时)?

我的图表比例代码如下:

y: {
    beginAtZero: true,
    grid:  {
        display: false,
        drawBorder: false,
        drawOnChartArea: false,
     },
     ticks: {
        display: true,
     },
   },
},
y1: {
     beginAtZero: true,
     position: 'right',
     grid: {
        display: false,
        drawBorder: false,
        drawOnChartArea: false,
     },
     ticks: {
        display: true,
     },
   },
}

示例图:

Alignment of Y axes

javascript charts chart.js dataset bar-chart
1个回答
0
投票

您之前的问题相同,但没有具体说明 您想要实现的选项,可以通过设置

y
y1
轴可编写脚本
min
max
来完成。在这种情况下, 使用比例公式需要设置的重要参数是
min
,而
max
可以设置为数据的最大值以避免 轴步长的下一个倍数的额外空间:

function computeMin(which, data){
    // computes min for scale `which` (0 -> 'y', 1 -> 'y1') such that the
    // level of 0 is the same for all datasets
    // note: there's no negative-only dataset
    const dataValues = data.datasets.map(dataset=>dataset.data),
        dataMin = dataValues.map(data => Math.min(0, ...data)),
        dataMax = dataValues.map(data => Math.max(0, ...data)),
        ratios = dataMin.map((min_i, i) => -min_i/(-min_i + dataMax[i])),
        bestRatio = Math.max(...ratios);
    if(ratios[which] < bestRatio){
        const delta = (dataMax[which] * bestRatio - dataMin[which] * (bestRatio - 1))/(bestRatio - 1);
        return dataMin[which] + delta;
    }
    return dataMin[which]
}

用作:

options: {
    ........... other options
    scales: {
        y: {
            .......... other y axis options
             ticks: {
                 display: true,
                 includeBounds: false
             },
             max: ({chart}) => computeMax(0, chart.data)
        },
        y1: {
            .......... other y1 axis options
            ticks: {
                display: true,
                includeBounds: false
            },
            max: ({chart}) => computeMax(1, chart.data)
        }
    }
}      

在演示片段中:

function computeMin(which, data){
    // computes min for scale `which` (0 -> 'y', 1 -> 'y1') such that the
    // level of 0 is the same for all datasets
    // note: no negative-only datasets are not supported, to support those
    // see https://jsfiddle.net/oruvz3dx/, https://jsfiddle.net/oruvz3dx/1
    const dataValues = data.datasets.map(dataset=>dataset.data),
        dataMin = dataValues.map(data => Math.min(0, ...data)),
        dataMax = dataValues.map(data => Math.max(0, ...data)),
        ratios = dataMin.map((min_i, i) => -min_i/(-min_i + dataMax[i])),
        bestRatio = Math.max(...ratios);
    if(ratios[which] < bestRatio){
        const delta = (dataMax[which] * bestRatio - dataMin[which] * (bestRatio - 1))/(bestRatio - 1);
        return dataMin[which] + delta;
    }
    return dataMin[which]
}


const config = {
    type: "bar",

    data: {
        labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
        datasets: [
            {
                label: 2023,
                data: [50, -59, -80, -81, -56, 55, 65, 108, 80, -41, 56, 55],

            },
            {
                label: 2024,
                data: [20, 65, 80, 102, 55, 56, 65, 59, 80, 81, 56, 55].map(x => x * 10),
                yAxisID: 'y1'
            },
        ]
    },

    options: {
        maintainAspectRatio: false,
        scales: {
            y: {
                grid: {
                    display: false,
                    drawBorder: false,
                    drawOnChartArea: false
                },
                ticks: {
                    display: true,
                    includeBounds: false
                },
                min: ({chart}) => computeMin(0, chart.data),
                max: ({chart}) => Math.max(...chart.data.datasets[0].data)
            },
            y1: {
                position: 'right',
                grid: {
                    display: false,
                    drawBorder: false,
                    drawOnChartArea: false,
                },
                ticks: {
                    display: true,
                    includeBounds: false
                },
                min: ({chart}) => computeMin(1, chart.data),
                max: ({chart}) => Math.max(...chart.data.datasets[1].data)
            },
        }
    }
};

new Chart('myChart', config);
<div style="height: 300px">
    <canvas id="myChart">
    </canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

该解决方案适应了问题的规定参数:只有两个数据集,其中没有一个只有负值。

此解决方案的泛化,允许具有仅负值、仅正值和混合正负值的多个数据集,在此fiddle中设置;这是该小提琴的版本,它缓存计算的

min
max
值,以避免重复计算。

© www.soinside.com 2019 - 2024. All rights reserved.