如何在Chart.js中对左下角的Y轴和X轴标签进行分组?

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

我正在使用 Chart.js v4.4.3。

我的目标是将 Y 轴标签和 X 轴标签分组以实现这样的目标:

chartjs-axes-group-design-goal

我无法在https://www.chartjs.org/docs/latest/axes/labelling.html中找到用于将这两个轴标签分组在一起的选项。

这可以通过 Chart.js 选项实现吗?我是不是错过了什么?

这是我到目前为止的选择,但这并不是我想要实现的目标。

{
  scales: {
    x: {
      title: {
        display: true,
        text: 'Day',
        align: 'start',
      },
    },
    y: {
      title: {
        display: true,
        text: 'Min',
        align: 'start',
      },
    },
  }
}

任何帮助将不胜感激!谢谢!

javascript charts chart.js bar-chart
1个回答
0
投票

配置轴标题的空间很小,您已经链接到 文档中列出可用选项的页面

有几种方法可以实现您所描述的目的,但没有一个像设置选项那么简单。

在我看来最直接、适应性最强的解决方案是使用自定义插件在画布上自己绘制混合标签。

下面的实现使用了 beforeUpdate 回调以获取插件的所有选项并调整填充以使标签适合画布,并且 afterDraw 在每次需要时实际渲染标签。

代码片段中的代码可以通过硬编码一些选项来简化,或者相反,它可以扩展到 包括其他选项,例如多个轴、左下角以外的其他角等。

//import {toFontString} from 'chart.js/helpers'; // in a module environment
const toFontString = Chart.helpers.toFontString; // with umd script

const plugin_mix_title = {
    id: 'mix_title',
    beforeUpdate(chart){
        let text = chart.options.plugins.mix_title.text;
        if(!text){
            const xTitle = chart.options.scales.x.title.text,
                xTitleDisplay = chart.options.scales.x.title.display,
                yTitle = chart.options.scales.y.title.text,
                yTitleDisplay = chart.options.scales.y.title.display;
            if(xTitle && yTitle && !xTitleDisplay && !yTitleDisplay){
                text = `${yTitle} / ${xTitle}`;
            }
        }
        if(text){
            const ctx = chart.ctx;
            const font = Object.assign({}, Chart.defaults.font,
                    chart.options.plugins.mix_title.font ?? {}),
                textColor = chart.options.plugins.mix_title.color ?? Chart.defaults.color;
            const fontString = toFontString(font);
            const margin_y = chart.options.scales.x.ticks.padding +
                    chart.options.scales.x.grid.tickLength,
                margin_x = chart.options.scales.y.ticks.padding +
                    chart.options.scales.y.grid.tickLength;
            ctx.save();
            ctx.font = fontString;
            const fm = ctx.measureText(text);
            ctx.restore();
            chart.options.layout.padding.left = Math.max(
                chart.options.layout.padding.left, Math.ceil(fm.width - margin_x));
            this._preComputed = {
                text, fontString, textColor, margin_x, margin_y
            }
        }
    },
    afterDraw(chart){
        const options = this._preComputed;
        if(options){
            const {text, fontString, textColor, margin_x, margin_y} = options;
            const ctx = chart.ctx;
            const x = chart.scales.y.right - margin_x,
                y = chart.scales.x.top + margin_y;
            ctx.save();
            ctx.font = fontString;
            ctx.textAlign = "right";
            ctx.textBaseline = "hanging";
            ctx.fillStyle = textColor;
            ctx.fillText(text, x, y);
            ctx.restore();
        }
    }
};

Chart.defaults.color = 'white';
const config =  {
    type: 'bar',
    data: {
        labels: ['05', '10', '15'],
        datasets: Array.from({length: 5}, (_, i)=>({
            label: 'D'+(i+1),
            data: Array.from({length: 3}, ()=>5+Math.floor(Math.random()*20)),
            backgroundColor: 'rgba(195, 192, 255, 0.7)',
        }))
    },
    options: {
        scales: {
            x: {
                ticks: {
                    padding: 10
                },
                title: {
                    //display: true,
                    text: 'Day',
                    //align: 'start',
                },
            },
            y: {
                title: {
                    //display: true,
                    text: 'Min',
                    //align: 'start',
                },
            }
        },
        categoryPercentage: 1,
        plugins:{
            legend:{
                display: false
            },
            mix_title: { // available options
                // font: Chart.defaults.font, // all items: size, family, style, lineHeight, weight
                color: "lightblue"//Chart.defaults.color,
                // text: null // if null (default), synthesize y.title/x.title
            }
        }
    },
    plugins:[plugin_mix_title]
};
new Chart('myChart', config);
<div style="height: 200px">
    <canvas id="myChart" style="background-color:rgb(0,0,48)">
    </canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

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