6

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,
                ..
            }
        ]
    }

3 Answers 3

5

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!

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for this. Well it doesn't answer my question but it is useful. However it's not working for me. I can position my text on the chart canvas and give my text a color with fillText and fillStyle however ctx.font doesn't have any effect. E.g: ctx.font = "bold 26px"; does nothing. Actually the font size takes on the size specified in the Chart.js option... title{fontSize:16}. Can you help? If not maybe I'll just use CSS and position a span in the title area!
You can use Animations Callbacks (onProgress or onComplete). I update my answer and you can use your code and test! Change CallBack type! In my answer the fontSize works for several lines! And you can add margin and padding to the label location
Thanks for your help Edi. I accepted your solution and updated my question showing how I used your information to solve my problem.
1

Use ChartJS subtitle option:

var ctx = document.getElementById('chart').getContext('2d');
var cfg = {
  type: 'bar',
  data: {
    labels: [1,2,3,4,5],
    datasets: [{label:'Frequency',data:[36,23,72,43,27]}]
  },
  options: {
    responsive: true,
    plugins: {
      title: {
        display: true,
        text: 'Chart Title',
        padding: {
          top: 10,
          bottom: 5
        },
        font: {
          size: 16
        }
      },
      subtitle: {
        display: true,
        text: 'Chart Subtitle',
        padding: {
          top: 0,
          bottom: 30
        },
        font: {
          size: 10,
          weight: 'bold'
        }
      }
    }
  }
};
var chart = new Chart(ctx, cfg);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>

<canvas id="chart"></canvas>

Comments

0

use proper font format like

ctx.font = 'bold 30px "Century Gothic"';

OR

ctx.font = 'bold 30px Arial';

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.