Chart js multiple titles - javascript

Is it possible to have multiple titles in Chart JS? https://www.chartjs.org/
At the current state I use the title as a description below the chart. I also need a title on top of the chart. Is it possible?
An alternative for my case would be if there was another way to implement a description at the bottom and keep the title as top title.
var chart = new Chart(ctx, {
type: 'line',
data: data,
options: {
title: {
display: true,
text: 'Custom Chart Title',
position: 'bottom',
}
}
});

You can use the Plugin Core API. It offers different hooks that may be used for executing custom code. In below code snippet, I use the afterDraw hook to draw a title on the canvas. That way you can draw as many titles as you want, define them of different style each and place them wherever it suits you.
Please note that inside chart options, I also defined some layout padding. This prevents the title from overlapping the chart bars.
layout: {
padding: {
top: 40
}
}
Chart.plugins.register({
afterDraw: chart => {
var ctx = chart.chart.ctx;
ctx.save();
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = "18px Arial";
ctx.fillStyle = "gray";
ctx.fillText('Top Title', chart.chart.width / 2, 20);
ctx.restore();
}
});
new Chart(document.getElementById('myChart'), {
type: 'bar',
data: {
labels: ['A', 'B', 'C', 'D'],
datasets: [{
data: [10, 12, 8, 6],
backgroundColor: ['red', 'blue', 'green', 'orange']
}]
},
options: {
layout: {
padding: {
top: 40
}
},
title: {
display: true,
text: 'Custom Chart Title',
position: 'bottom',
},
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="myChart" height="100"></canvas>

Related

Changing legend text in chart js causing issues

I'm trying to shorten my chart legends, so I'm using the beforeRender plugin to change the text of the legend. However, once the chart is drawn, it seems to keep the original label size (see below snippet, legends are offset to the left instead of in the centre and if you click on orange, it toggles one of the earlier items).
The same happens if I try in beforeDraw and if I use beforeInit or beforeLayout, the legends don't seem to have been created yet.
Is there any way to get the chart to redraw the legends with the new text? Or change the legend text so that it is rendered properly?
var ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx, {
type: 'pie',
data: {
labels: ['red - some other text that appears after', 'blue - some other text that appears after', 'green - some other text that appears after', 'orange - some other text that appears after'],
datasets: [{
data: [4, 2, 10, 3],
backgroundColor: ['red', 'blue', 'green', 'orange'],
}],
},
options: {
responsive: true,
},
plugins: [{
beforeRender: chart => {
chart.legend.legendItems.forEach(label => {
const labelParts = label.text.split(' - ');
const newLabel = label;
newLabel.text = labelParts[0];
return newLabel;
});
},
}],
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.js"></script>
<div style="width: 100%">
<canvas id="canvas"></canvas>
</div>
A better approach would be to use a custom generateLabels function like so:
var ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx, {
type: 'pie',
data: {
labels: ['red - some other text that appears after', 'blue - some other text that appears after', 'green - some other text that appears after', 'orange - some other text that appears after'],
datasets: [{
data: [4, 2, 10, 3],
backgroundColor: ['red', 'blue', 'green', 'orange'],
}],
},
options: {
responsive: true,
legend: {
labels: {
generateLabels: function(chart) {
const data = chart.data;
if (data.labels.length && data.datasets.length) {
return data.labels.map(function(label, i) {
const meta = chart.getDatasetMeta(0);
const style = meta.controller.getStyle(i);
return {
text: label.split(' - ')[0],
fillStyle: style.backgroundColor,
strokeStyle: style.borderColor,
lineWidth: style.borderWidth,
hidden: isNaN(data.datasets[0].data[i]) || meta.data[i].hidden,
// Extra data used for toggling the correct item
index: i
};
});
}
return [];
}
}
}
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.js"></script>
<div style="width: 100%">
<canvas id="canvas"></canvas>
</div>

Chart.js Treemap Custom text

In my code below, I am able to draw a Treemap and also display the tag in each tree cell. But I want to add some custom text next to my tag,
Like say I want the word 'Language' to appear in each tree map cell. I tried the formatter options, But its not working for the version of chart.js I am using. Kindly provide me a solution for the specific version I am using. Since I have multiple other charts defined and changing the version would cause issues.
var topTags = [
{tag:'android',num:42657},{tag:'reactjs',num:38844},{tag:'php',num:34381},{tag:'sql',num:29996},
];
var canvas = document.getElementById("treemap");
var ctx = canvas.getContext("2d");
var chart = window.chart = new Chart(ctx, {
type: "treemap",
data: {
datasets: [{
tree: topTags,
key: "num",
groups: ['tag'],
spacing: 0.5,
borderWidth: 1.5,
fontColor: "black",
borderColor: "grey"
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
tooltips: { enabled: false }
}
});
CHART.JS AND TREEMAP VERSION :
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-chart-treemap#0.2.3"></script>
The formatter option only got added in version 2 of the treemap chart type, the scriptable option is only available in version 1 so the best way for you to get the extra text is by editing your original data array first and adding the text to it that way like so:
let topTags = [{
tag: 'android',
num: 42657
}, {
tag: 'reactjs',
num: 38844
}, {
tag: 'php',
num: 34381
}, {
tag: 'sql',
num: 29996
}, ];
topTags = topTags.map(e => ({
num: e.num,
tag: `Lang: ${e.tag}`
}))
const canvas = document.getElementById("chart");
const ctx = canvas.getContext("2d");
const chart = window.chart = new Chart(ctx, {
type: "treemap",
data: {
datasets: [{
tree: topTags,
key: "num",
groups: ['tag'],
spacing: 0.5,
borderWidth: 1.5,
fontColor: "black",
borderColor: "grey",
}]
},
options: {
maintainAspectRatio: false,
legend: {
display: false
},
tooltips: {
enabled: false
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-chart-treemap#0.2.3"></script>
<canvas id="chart"></canvas>

Styling problems with Chart.Js

How can I add these styles to my graph? I'm having trouble finding it in the documentation for it, and the other forums aren't very helpful. I am using Flask for the backend, so that's why the data values look like that.
Labels on top of bars
Change font size on both axis
Set y scale as a fixed value (0,8)
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var options = {
scales: {
yAxes: [{
ticks: {
fontSize: 40
}
}]
}
}
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Lithium Battery', 'Other Mfg', 'Delivery', 'Tailpipe', 'Fuel Cycle', 'Disposal', 'Total'],
datasets: [{
label: 'ICEV CAR (MTCO2e/Year)',
labels: [
"{{data['battery_icev_car']}}",
"{{data['other_mfg_icev_car']}}",
"{{data['delivery_icev_car']}}",
"{{data['tailpipe_icev_car']}}",
"{{data['fuel_cycle_icev_car']}}",
"{{data['disposal_icev_car']}}",
"{{data['total_icev_car']}}"
],
data: [ /* errors are normal, fixes when server ru
[0, {{data['y1_icev']}}],
[{{data['y1_icev']}}, {{data['y2_icev']}}],
[{{data['y2_icev']}}, {{data['y3_icev']}}],
[{{data['y3_icev']}}, {{data['y4_icev']}}],
[{{data['y4_icev']}}, {{data['y5_icev']}}],
[{{data['y5_icev']}}, {{data['y6_icev']}}],
[0, {{data['y6_icev']}}]
],
backgroundColor: [
'rgba(0,0,0,0.9)'
],
borderColor: [
'rgba(0,0,0,1)'
],
borderWidth: 1,
borderSkipped: false
}]
},
options: {
responsive: true,
plugins: {
legend: {
labels: {
// This doesn't work on axis
font: {
size: 20
}
}
}
},
y: {
beginAtZero: true
}
}
});
</script> </script>
Since your config is not working I assume you are using V3, in which case the solution is as followed:
For point one you need to use an external plugin, you can write your own or use the datalabels plugin
For your second problem you need to style it as a font object as told in the documentation like so:
options: {
scales: {
y:{
ticks:{
font:{
size: 50
}
}
}
}
}
For your last part you can set the stepSize to 0.8

Chart.js - change which data the legend uses for the coloured box

I have a bar chart that always shows 4 bars. The bars are coloured dynamically. It looks like the coloured box takes its colour from the first data. I would like to use the colour from the 4th (last) data value. Maybe the options:plugins:legend:label:sort function helps but I don't understand what it does.
options
const options = {
scales: {
x: {
grid: {
display: false,
color: 'rgba(0,0,0)'
}
},
y: {
display: false,
min: 0,
max: 4
},
},
plugins: {
legend: {
position: 'bottom'
}
}
}
So I don't know if I can change the data that the box color comes from, or if there is a config option somewhere where I can change it manually.
You can use the generateLabels function as described here.
Please take a look at below runnable sample code and see how it works.
new Chart('myChart', {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow'],
datasets: [{
label: 'My Dataset',
data: [300, 50, 100],
backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56']
}]
},
options: {
responsive: false,
plugins: {
legend: {
labels: {
generateLabels: chart => {
let ds = chart.data.datasets[0];
let color = ds.backgroundColor[ds.backgroundColor.length - 1];
return [{
datasetIndex: 0,
text: ds.label,
fillStyle: color,
strokeStyle: color
}];
}
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>
<canvas id="myChart" height="180"></canvas>
Following up with #uminder's answer, if you want to keep the hide/show chart and the line-through style after clicking on the legend, you can add the following line:
options: {
responsive: false,
plugins: {
legend: {
labels: {
generateLabels: chart => {
let ds = chart.data.datasets[0];
let color = ds.backgroundColor[ds.backgroundColor.length - 1];
return [{
datasetIndex: 0,
text: ds.label,
fillStyle: color,
strokeStyle: color,
+ hidden: !chart.isDatasetVisible(0)
}];
}
}
}
}
}

Bar chart legend adjustments - Chart JS

I'm new in Chart JS and I have a bar chart with the legend displayed bellow the chart:
var data = {
labels: [],
datasets: [{
label: 'Disk C',
backgroundColor: "#000080",
data: [80]
}, {
label: 'Disk D',
backgroundColor: "#d3d3d3",
data: [90]
},
{
label: 'Memory',
backgroundColor: "#add8e6",
data: [45]
}]
};
var ctx = document.getElementById("mybarChart");
ctx.height = 300;
var mybarChart = new Chart(ctx, {
type: 'bar',
responsive: true,
data: data,
options: {
legend: {
display: true,
position: 'bottom'
},
scales: {
yAxes: [{
display: false,
ticks: {
beginAtZero: true
},
gridLines: {
color: "rgba(0, 0, 0, 0)",
}
}],
xAxes: [{
display: false,
gridLines: {
color: "rgba(0, 0, 0, 0)",
},
barPercentage: 0.5,
categoryPercentage: 0.5
}]
}
}
});
But the legend should be something like :
It is possible to make the colors rectangles much more smaller and the values to be displayed one below another because in my example the labels are displayed in a single row?
Unfortunately, there is no way to customize the default legend in the manner that you are wanting. Fortunately, however, chart.js thought of this and provided a mechanism for you to generate and style your own legend outside of the canvas object (using regular html/css).
You can use the legendCallback options property to define a method that generates your legend html and then call the chart .generateLegend() prototype method to place into your page. Here is what I mean.
HTML for my page.
<div style="width:25%;">
<canvas id="mybarChart"></canvas>
<div id="legend"></div>
</div>
Then I define how the legend will look in the 'legendCallback' option property.
legendCallback: function(chart) {
var text = [];
text.push('<ul class="' + chart.id + '-legend">');
for (var i = 0; i < chart.data.datasets.length; i++) {
text.push('<li><div class="legendValue"><span style="background-color:' + chart.data.datasets[i].backgroundColor + '"> </span>');
if (chart.data.datasets[i].label) {
text.push('<span class="label">' + chart.data.datasets[i].label + '</span>');
}
text.push('</div></li><div class="clear"></div>');
}
text.push('</ul>');
return text.join('');
}
Finally, I add the legend html to my page.
$('#legend').prepend(mybarChart.generateLegend());
As always, here is a codepen example showing a working solution. You can change your legend look and feel simply by changing the html that is generated by the callback and using css.

Categories

Resources