📈
Chart.jsで左右のy軸の間隔(ticks)を揃える
Chart.jsのMulti Axisのチュートリアルで、const NUMBER_CFG = {count: DATA_COUNT, min: 0, max: 1000};
と乱数を変更すると、次のように出てくることがあります。
左側が7等分、右側が10等分で表示されているため、視覚的に分かりにくいかと思います。Chart.jsが与えられたデータをもとに「nice」な見た目になるように調整してくれた結果なのですが、ここに手を加えていこうと思います。
完成例
ソースコード
手を加えたソース,これをSetupの部分のコードと差し替える
const DATA_COUNT = 7;
const NUMBER_CFG = {count: DATA_COUNT, min: 0, max: 100};
function generateRandomIntegers(cfg) {
const {count, min, max} = cfg;
const numbers = [];
for (let i = 0; i < count; i++) {
numbers.push(Math.floor(Math.random() * (max - min + 1)) + min);
}
return numbers;
}
const labels = Utils.months({count: 7});
const dataset1Data = generateRandomIntegers(NUMBER_CFG);
const dataset2Data = generateRandomIntegers(NUMBER_CFG);
const data = {
labels: labels,
datasets: [
{
label: 'Dataset 1',
data: dataset1Data,
borderColor: 'rgb(255, 99, 132)',
backgroundColor: 'rgba(255, 99, 132, 0.5)',
yAxisID: 'y',
},
{
label: 'Dataset 2',
data: dataset2Data,
borderColor: 'rgb(54, 162, 235)',
backgroundColor: 'rgba(54, 162, 235, 0.5)',
yAxisID: 'y1',
}
]
};
const maxY = getNextRoundedValue(Math.max(...dataset1Data));
const maxY1 = getNextRoundedValue(Math.max(...dataset2Data));
function getNextRoundedValue(value) {
const valueStr = value.toString();
const firstDigit = parseInt(valueStr[0]);
const newFirstDigit = firstDigit + 1;
const zeros = '0'.repeat(valueStr.length - 1);
const result = parseInt(newFirstDigit + zeros);
return result;
}
const config = {
type: 'line',
data: data,
options: {
responsive: true,
interaction: {
mode: 'index',
intersect: false,
},
stacked: false,
plugins: {
title: {
display: true,
text: 'Chart.js Line Chart - Multi Axis'
}
},
scales: {
y: {
type: 'linear',
display: true,
position: 'left',
min: 0,
max: maxY,
ticks: {
count: 11,
}
},
y1: {
type: 'linear',
display: true,
position: 'right',
min: 0,
max: maxY1,
ticks: {
count: 11,
},
// grid line settings
grid: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
},
}
},
};
1:最大値をキリの良い数字で決める
今回は縦軸の最大値を以下のようにしました。このやり方である必要はないので、要件ややりたいことに応じてロジックを作れば良いです。
- ランダムな整数を生成するように変更する。
- データ内で最大の値を取得する。
- 最大の値の先頭の位に1を足し、それ以外の数字は0にする。
例: 4321->5000, 123456->200000, 334->400
// Copilot君に出してもらったコード
function generateRandomIntegers(cfg) {
const {count, min, max} = cfg;
const numbers = [];
for (let i = 0; i < count; i++) {
numbers.push(Math.floor(Math.random() * (max - min + 1)) + min);
}
return numbers;
}
const dataset1Data = generateRandomIntegers(NUMBER_CFG);
const dataset2Data = generateRandomIntegers(NUMBER_CFG);
const maxY = getNextRoundedValue(Math.max(...dataset1Data));
const maxY1 = getNextRoundedValue(Math.max(...dataset2Data));
// Copilot君に出してもらったコード
function getNextRoundedValue(value) {
const valueStr = value.toString();
const firstDigit = parseInt(valueStr[0]);
const newFirstDigit = firstDigit + 1;
const zeros = '0'.repeat(valueStr.length - 1);
const result = parseInt(newFirstDigit + zeros);
return result;
}
2:configを設定する
options.scales.{AxisID}(今回だとy,y1)の項目で以下のように設定します。それぞれ
- min: 軸の最小値
- max: 最大値
- ticks.count: 軸のメモリの本数、分割したい数+1で設定
ticks.countは今回10分割したいので11としています。
min: 0,
max: maxY // or maxY1,
ticks: {
count: 11,
},
まとめ
軸の分割数を左右揃えて見やすくしたい場合、options.scales.ticks.countを揃えるとできます。その際軸の最大値を割り切れる数字で設定することで、綺麗に表示できるようになります。
最大値を特に明示しないとデータ内の最大値が参照される(左)
Discussion