Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I specify a different font size for each row of text in Chart Title?

I am using Chart.js Version: 2.7.3

My Chart Title has three rows. I'd like to make the top row font size 16 then the second 14 and the third 12. I'm not sure if it's possible and haven't found a way.

Here is a portion of my code that defines the options for my Chart...

options: {
    title: {
        display: true,
        // Supply the title as an array and each array index prints on a separate line in the title section
        text: ['My Chart','Last Month', 'Local Time'],
        fontSize: 16,
        callbacks: {
            drawTitle: function(pt, vm, ctx, opacity) {
                    console.log("title.length: " + title.length);
                    var title = vm.title;

                    if (title.length) {
                        ctx.textAlign = vm._titleAlign;
                        ctx.textBaseline = 'top';

                        var titleFontSize = vm.titleFontSize;
                        var titleSpacing = vm.titleSpacing;

                        ctx.fillStyle = mergeOpacity(vm.titleFontColor, opacity);
                        ctx.font = helpers.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily);

                        var i, len;
                        for (i = 0, len = title.length; i < len; ++i) {
                            ctx.fillText(title[i], pt.x, pt.y);
                            pt.y += titleFontSize + titleSpacing; // Line Height and spacing

                            if (i + 1 === title.length) {
                                pt.y += vm.titleMarginBottom - titleSpacing; // If Last, add margin, remove spacing
                            }
                        }
                    }
                }
            }
        },

I know you can specify a "fontSize" but this applies to all Text in the Chart Title. I want a different fontSize for each row of text. I tried specifying a Callback but I don't see the console.log() message when I check in Chrome F12 devtools.

Is there a way in Chart.js to specify a different fontSize for each row in the Chart Title?

Thank you!

Update about the Solution

I have accepted the answer from Edi Carlos because this gave the helpful advice about how to attach formatted text to a canvas element and that this can be done within a Chart.js animation callback.

My Chart is a Scatter Plot with Tooltips enabled. With the accepted solution when hovering over a plotted point the fillText may disappear or change position on the screen. I found the text would also disappear if I used F12 Chrome Dev Tools. The same happens in the jsfiddle in the accepted answer... if you enable Tooltips... try hovering over a bar chart or hitting F12.

To stop the fillText from shifting position when hovering over a ToolTip I found I had to specify:

ctx.textBaseline = 'top';
ctx.textAlign = 'center';

To stop the fillText from disappearing when hitting F12 I found I had to CSS style the canvas element with absolute position.

#canvas{
    position:absolute;
}

Here is a section of the code in my Chart.js options that shows how to specify a different font size and style for each row of text you may have in a Chart.js Chart Title:

options: {
    animation: {
        onProgress: function(animation) {
            ctx.textBaseline = 'top';
            ctx.textAlign = 'center';

            // Set the font size and text position for the 2nd row in the Chart title
            ctx.font = "bold 14px 'Helvetica Neue', Helvetica, Arial, sans-serif";
            ctx.fillStyle = "#666";
            ctx.fillText("Last 24 Hours", 610, 32);

            // Set the font size and text position for the 3rd row in the Chart title
            ctx.font = "bold 12px 'Helvetica Neue', Helvetica, Arial, sans-serif";
            ctx.fillStyle = "#666";
            ctx.fillText("Local Time | Limit=None", 610, 53);
        }
    },      
    title: {
        display: true,
        text: ['Sensor Chart','             ', '                         '],
        fontSize: 16
        }
    }

Chart.js lets you supply an array of strings as the title. Then each array index prints out on a separate line. I left spaces in the text: [] array index 1 and 2 so there would be blank space in the Chart Title to position the ctx.fillText() into.

Suggested addition to Chart.js

Overall this still feels like a slightly hacky way to do it. I think Chart.js should have a more integrated solution. Something like in the same way you can specify more than one y-axis each with its own properties using:

yAxes: [
        {
            id: 'A',
            ..
            ..
        },
        {
            id: 'B',
            ..
            ..
        }
    ]

It would be great if you could specify styling for multiple rows in a Chart Title with something like:

title: {
    display: true,
    titleRows: [
            {
                id: 'A',
                text: 'Row1',
                fontSize: 16,
                ..
            },
            {
                id: 'B',
                text: 'Row2',
                fontSize: 14,
                ..
            },
            {
                id: 'C',
                text: 'Row3',
                fontSize: 12,
                ..
            }
        ]
    }
like image 768
FlexMcMurphy Avatar asked Apr 16 '19 15:04

FlexMcMurphy


People also ask

How do I change the font of a chart title in Excel?

Right-click inside the text box and then click the formatting options that you want. You can also use the formatting buttons on the Ribbon (Home tab, Font group). To format the whole title, you can right-click it, click Format Chart Title, and then select the formatting options that you want.

Which tab is used to change font color and size the text in a chart?

On the Home tab, in the Font group, choose the arrow next to Font Color, and then select a colour. You can also use the formatting options on the Mini toolbar to quickly format text.


1 Answers

You can to use fillText() Method using Chart.js Version: 2.7.3

Write "Network!" and "Stackoverflow" (with gradient) on the canvas, using fillText():

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

ctx.font = "20px Georgia";
ctx.fillText("Network", 10, 50);

ctx.font = "30px Verdana";
// Create gradient
var gradient = ctx.createLinearGradient(0, 0, c.width, 0);
gradient.addColorStop("0"," magenta");
gradient.addColorStop("0.5", "blue");
gradient.addColorStop("1.0", "red");
// Fill with gradient
ctx.fillStyle = gradient;
ctx.fillText("Stackoverflow", 10, 90);

The fillText() method draws filled text on the canvas. The default color of the text is black. Use the font property to specify font and font size, and use the fillStyle property to render the text in another color/gradient.

My Fiddle example

Update -> You can use Animations Callbacks (onProgress or onComplete) to do that eg:

options: {
        animation: {
            onProgress: function(animation) {
                // code above
            }
        }
    }

Update 2 -> Complete Code

var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
        datasets: [{
            data: [2, 2, 3, 5, 2, 3],
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255, 99, 132, 1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
    tooltips: {
         enabled: false
    },
      legend: {
          display: false
      },
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero: true
                }
            }]
        },
        animation: {
            onProgress: function(animation) {
                var c = document.getElementById("myChart");
                var ctx = c.getContext("2d");

                ctx.font = "20px Georgia";
                ctx.fillText("1 - Network", 45, 30);                

                ctx.font = "30px Verdana";
                // Create gradient
                var gradient = ctx.createLinearGradient(0, 0, c.width, 0);
                gradient.addColorStop("0", "magenta");
                gradient.addColorStop("0.5", "blue");
                gradient.addColorStop("1.0", "red");
                // Fill with gradient
                ctx.fillStyle = gradient;
                ctx.fillText("2 - Stackoverflow", 45, 70);                
            }
        }
    }
});

full Fiddle

I hope helps!

like image 158
Edi Avatar answered Sep 20 '22 03:09

Edi