我正在尝试比较 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,
},
},
}
示例图:
与您之前的问题相同,但没有具体说明 您想要实现的选项,可以通过设置
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
值,以避免重复计算。