Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making the labels responsive in chart js

I'm having a hard time making the labels in the y-axis responsive.I want the labels to move to multiple lines and have responsive font sizes when the space is not enough.I'm using the chart.js datalabels library for labelling on top of horizontalBar Graph.Also the labels are getting hidden due to the outer chart container.

var chart = new Chart('ctx', {
    type: 'horizontalBar',
    data: {
        labels: ["Something something something", "blah blah..", "blah blah..","Something something something"],
        datasets: [{
            data: [6, 87, 56,25,100,65],
            backgroundColor: "#4082c4"
        }]
    },
    options:{
        responsive: true,
        maintainAspectRatio: false,
        plugins: {
            datalabels: {
                color: 'black',
                anchor: "end",
                align: "right",
                offset: 20,
                display: function (context) {
                    return context.dataset.data[context.dataIndex];
                },
                font: {
                    weight: 'bold',
                    size: 26
                },
                formatter: Math.round
            }
        },
        legend: {
            "display": false
        },
        tooltips: {
            "enabled": false
        },
        scales: {
            yAxes: [{
                barPercentage: 1.0,
                gridLines: {
                    display: false
                },
                ticks: {
                    fontSize: 20,
                    beginAtZero: true,
                }
            }],
            xAxes: [{
                gridLines: {
                    display: false
                },
                ticks: {
                    min: 0,
                    max: 100,
                    stepSize: 20
                }
            }]
        }
    }
    })

The numbers in the right side of the bar also gets clipped of.I want the chart to be at the center horizontally.In the browser the chart looks like thisenter image description here- Link to the fiddle:-https://jsfiddle.net/24wdpfxL/

like image 410
Rahul jhawar Avatar asked May 22 '18 19:05

Rahul jhawar


2 Answers

You can do this, but it's a bit hack-y.

First the data labels. In the datalabels config section, you can try something like:

            /* Adjust data label font size according to chart size */
            font: function(context) {
                var width = context.chart.width;
                var size = Math.round(width / 32);

                return {
                    weight: 'bold',
                    size: size
                };
            }

Change the size calculation as necessary.

For the y-axis labels, there's an answer here, however apparently since Chart.js 2.7.0, the line:

c.scales['y-axis-0'].options.ticks.fontSize

..should be changed to:

c.scales['y-axis-0'].options.ticks.minor.fontSize

(ref)

So to scale the y-axis labels font size according to chart height, it might look like:

plugins: [{
    /* Adjust axis labelling font size according to chart size */
    beforeDraw: function(c) {
        var chartHeight = c.chart.height;
        var size = chartHeight * 5 / 100;
        c.scales['y-axis-0'].options.ticks.minor.fontSize = size;
    }
}]

Note: This requires "maintainAspectRatio:" to be set to "true".

There's still one problem however, and that's that the part of the chart containing the y-axis labels will remain at the same pixel width even when resized.

We need to also resize this area to keep it at a constant % of the overall chart width, e.g. 40%, instead of a fixed pixel width (added to yAxes config section):

        /* Keep y-axis width proportional to overall chart width */
        afterFit: function(scale) {
            var chartWidth = scale.chart.width;
            var new_width=chartWidth*0.4;

            scale.width = new_width;
        }

(You might not notice this as a problem with your original example, since there is a oversized line that seems to cause the y-axis width to keep expanding when the window is enlarged. But when the labels don't overflow, then the width stays constant unless the above is used.)

Complete jsFiddle: https://jsfiddle.net/0kxt25v3/2/ (fullscreen)

I'm not sure about wrapping labels on to the next line, you might just need to pre-process the labels to limit the maximum number of characters per label.

I also haven't attempted to scale the x-axis label font sizes, but it should be easy enough to add it in to the "beforeDraw:" section.

like image 160
Stephen G Avatar answered Jan 03 '23 05:01

Stephen G


If you're using chartjs-plugin-datalabels; here's how i was able to make the labels responsive. Considering the chart may have variable width and height, we can get the average of both (height and width) and calculate the font size. I am also setting the max font size limit to 12.

    datalabels: {

                font: function (context) {
                    var avgSize = Math.round((context.chart.height + context.chart.width) / 2);
                    var size = Math.round(avgSize / 32);
                    size = size > 12 ? 12 : size; // setting max limit to 12
                    return {
                        size: size,
                        weight: 'bold'
                    };
                },
    }
like image 25
Syed Asim Avatar answered Jan 03 '23 06:01

Syed Asim