我正在尝试创建一个折线图,在 Chartjs 的一个类别中最多可以有两个点。在“示例”中,标签和数据均作为数组传递,因此每个标签只能有一个点。我最多想要两点。 我尝试在数据中添加额外的条目,但额外的条目没有执行任何操作。
data: {
datasets: [{
data: [10, 20, 30, 40, 50, 60, 70] // Only the first 6 entries are shown.
}],
labels: ['January', 'February', 'March', 'April', 'May', 'June']
},
data
应该是一个数据点数组,而
labels
数组应该为这些数据点提供 x 轴值(如果 x 轴的类型为 category
),
这是 line
类型图表的默认设置。假设我们的 data
看起来像这样:
const data = {
datasets: [{
data: [10, 20, 30, 40, 50, 60, 70, 80]
}],
labels: ['January', 'February', 'February', 'March', 'April', 'May', 'June', 'June'],
};
通过它,我们定义了这样一个事实:两个类别,一个用于
February
的一个类别和一个用于
June
的类别有两个点,而其他类别有一个点;如果想避免容易出现拼写错误的文本重复,则可以使用其他可能的约定。为了更好地控制 x 轴的点位置和标签,您可以使用(可能隐藏的)线性轴,并在数据集中设置相关的 x
值
data
。有两种可能:第一种,如果希望类别大小相同,那么有两个点的类别中的点会靠得更近。 在这种情况下,可以使用辅助隐藏线性 x 轴来定位点,同时显示带有不重复标签的统一类别 x 轴:
const data = {
datasets: [{
data: [10, 20, 30, 40, 50, 60, 70, 80]
}],
labels: ['January', 'February', 'February', 'March', 'April', 'May', 'June', 'June'],
};
let xi = 0;
data.datasets.forEach(dataset => {
dataset.data = dataset.data.map((y, i) => {
let x = xi + 0.5;
if(data.labels[i] === data.labels[i-1]){
x += 1/6;
}
else if(data.labels[i] === data.labels[i+1]){
x -= 1/6;
xi -= 1;
}
xi += 1;
return ({x, y});
})
});
const options = {
maintainAspectRatio: false,
plugins: {
tooltip:{
callbacks: {
title: ([{dataIndex}]) => data.labels[dataIndex]
}
},
legend: {
display: false,
}
},
scales: {
x: {
display: false,
type: 'linear',
},
x2:{
type: 'category',
offset: true,
labels: [... new Set(data.labels)],
grid: {
color: 'rgba(0,0,0,0.4)',
offset: true
}
},
y: {
beginAtZero: true,
},
},
};
new Chart('myChart', {type: 'line', options, data});
<canvas style="height: 160px" id="myChart"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
第二种情况
,如果你想保持点等距并具有可变宽度的类别,这样具有两个点的类别将是一个点的两倍大小。
在这种情况下,我们应该只保留线性 x 轴可见,但修改其标签以对应于原始 data.labels
const data = {
datasets: [{
data: [10, 20, 30, 40, 50, 60, 70, 80]
}],
labels: ['January', 'February', 'February', 'March', 'April', 'May', 'June', 'June'],
};
data.datasets.forEach(dataset => {
dataset.data = dataset.data.map((y, i) => ({x: i+0.5, y}));
});
const options = {
maintainAspectRatio: false,
plugins: {
tooltip:{
callbacks: {
title: ([{dataIndex}]) => data.labels[dataIndex]
}
},
legend: {
display: false,
}
},
scales: {
x: {
type: 'linear',
min: 0,
max: data.labels.length,
ticks: {
stepSize: 0.5,
callback: (value) => {
const idx = Math.floor(value),
label = data.labels[idx];
if(Math.abs(Math.round(value) - value) < 1e-6){
if(label === data.labels[idx - 1]){
return label;
}
else{
return null;
}
}
else{
if(label === data.labels[idx - 1] || label === data.labels[idx + 1]){
return null;
}
return label;
}
}
}
},
x2:{
type: "linear",
min: 0,
max: data.labels.length,
ticks: {
display: false,
stepSize: 0.5,
callback(value, ...args){
if(value === this.max || value === this.min){
return '';
}
if(Math.abs(Math.round(value) - value) < 1e-6){
const idx = Math.floor(value),
label = data.labels[idx];
if(label === data.labels[idx - 1]){
return null;
}
else{
return '';
}
}
else{
return null;
}
}
},
grid: {
color: 'rgba(0,0,0,0.4)',
drawTicks: false
//offset: true
}
},
y: {
beginAtZero: true,
//display: false,
},
},
};
new Chart('myChart', {type: 'line', options, data});
<canvas style="height: 160px" id="myChart"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>