我使用了以下图形配置来渲染图形:
{
type: 'horizontalBar',
indexAxis: 'y',
barThickness: 12,
scales: {
x: {
suggestedMax: 6,
suggestedMin: 0,
grid: {
display: false,
drawBorder: false,
},
ticks: {
stepSize: 2,
callback: function (value, index, ticks) {
return value ? value + 'h' : value;
},
}
},
y: {
type: 'category',
grid: {
drawBorder: false,
borderDash: [4, 3],
color: "#C2C8CD",
drawTicks: false,
offset: false,
},
ticks: {
}
}
}
我想要什么:
请帮助使用
react-chartjs-2
渲染此图表。
如果你想要实现的是让网格线从正下方穿过 每个条形,这不是标准功能,因为网格线 穿过栏的中间(使用
offset: false
)
或穿过条之间的空间中间。
您可以使用
chartjs-plugin-annotation
来绘制注释线
而不是网格线;除此之外,我可以想到两种方法来做到这一点:
一个使用技巧,另一个使用 hack。
技巧是在实际数据集之后添加一个空数据集。那 将在 y 轴上为此数据集的条分配一个空白空间 每个真实的酒吧。您还必须进行一些调整:设置
options.scales.y.ticks.align
至 'end'
(或设置匹配值
对于 options.scales.y.ticks.labelOffset
,请参阅 文档)
正确对齐刻度标签;禁用(过滤掉)图例条目
对于虚拟数据集;调整 y
刻度的 x
位置。
这里有一组选项可以做到这一点 - 我使用注释来删除错误或 您的帖子中多余的选项:
new Chart('myChart', {
type: 'bar',
data: {
labels: ["Awake", "Deep", "Light", "Rem"],
datasets: [
{
label: 'data',
backgroundColor: ['orange', 'green', 'lightBlue', 'black'],
data: [3*6/100, 6*6/100, 76*6/100, 15*6/100]
},
{} // empty "phantom" dataset
]
},
options: {
//type: 'horizontalBar', // no such thing, also type: not here
indexAxis: 'y',
barThickness: 16,
scales: {
x: {
suggestedMax: 6,
suggestedMin: 0,
grid: {
display: false,
//drawBorder: false, // this is border.display
},
ticks: {
stepSize: 2,
callback: function (value) {
return value ? value + 'h' : value;
},
maxRotation: 0
},
position:{ // set the x axis position below the last line
y: ({scale: {chart}}) => chart.scales.y.max
}
},
y: {
//type: 'category', // default
grid: {
//drawBorder: false, // this is border.display
//borderDash: [4, 3], // this is under border.dash
color: "#C2C8CD",
drawTicks: false,
offset: false,
},
ticks: {
align: 'end'
},
border:{
display: true,
dash: [4, 3]
}
}
},
plugins: {
legend: {
display: false,
labels: { // if display enabled, filter out empty dataset
filter(item){
return !!item.text;
}
}
},
datalabels:{
anchor: 'end',
align: 'end',
formatter: function(value, context) {
const sum = context.dataset.data.reduce((s, x) => s + x);
return Math.round(value/sum*100).toFixed(1).replace(/\.?0+$/, '') + '%';
}
}
}
},
plugins: [ChartDataLabels],
});
<div style="max-width:400px; height: 200px">
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>
hacky解决方案将基于一个插件,该插件可以移动 条形图位于网格线的顶部;那个动作可以做 在
beforeDatasetDraw
钩子中,但应注意
每个条仅移动一次,而 beforeDatasetDraw
处理程序
可能会被调用几次。
new Chart('myChart', {
type: 'bar',
data: {
labels: ["Awake", "Deep", "Light", "Rem"],
datasets: [
{
label: 'data',
backgroundColor: ['orange', 'green', 'lightBlue', 'black'],
data: [3*6/100, 6*6/100, 76*6/100, 15*6/100]
}
]
},
options: {
indexAxis: 'y',
barThickness: 16,
clip: false, // allow the for the bar to overflow to the padding
scales: {
x: {
suggestedMax: 6,
suggestedMin: 0,
grid: {
display: false,
drawBorder: false, // this is border.display
},
ticks: {
stepSize: 2,
callback: function (value) {
return value ? value + 'h' : value;
},
maxRotation: 0
},
position:{ // set the x axis position below the last line
y: ({scale: {chart}}) => chart.scales.y.max
}
},
y: {
grid: {
color: "#C2C8CD",
drawTicks: false,
offset: false,
},
ticks: {
//align: 'end', OR:
labelOffset: function({scale}){
const chart = scale.chart;
return -chart.getDatasetMeta(0).data[0].height/2 ||
(scale.getPixelForValue(0) - scale.getPixelForValue(1/3));
},
},
border:{
display: false,
dash: [4, 3]
},
}
},
plugins: {
legend: {
display: false
},
datalabels: {
anchor: 'end',
align: 'end',
formatter: function(value, context) {
const sum = context.dataset.data.reduce((s, x) => s + x);
return Math.round(value/sum*100).toFixed(1).replace(/\.?0+$/, '') + '%';
}
}
}
},
plugins: [
ChartDataLabels,
{
beforeDatasetDraw(_, {meta}){
if(meta.$shifted || meta.type !== 'bar' || !meta.data[0]?.height){
// shift bars only once, on bars only and after height has been computed
// assumes there's no initial animation on barWidth.
return;
}
meta.data.forEach(
(elem) => {elem.y -= elem.height/2;}
);
meta.$shifted = true;
}
}
],
});
<div style="max-width:400px; height: 200px">
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>