如何更改react-chartjs-2中水平条的偏移量

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

我使用了以下图形配置来渲染图形:

{
    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
渲染此图表。

javascript reactjs chart.js react-chartjs-2
1个回答
0
投票

如果你想要实现的是让网格线从正下方穿过 每个条形,这不是标准功能,因为网格线 穿过栏的中间(使用

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>

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