Chart.js Formatting dual axis and labels - javascript

jsfiddle here.
First time using Chart.js and I cannot find an example with the whole code to review. I have the following data for 3 months to chart:
Project hours billed, Project hours not billed (stacked bar, for each month)
Billed Amount, To Be Billed amount (stacked bar for each month)
I want to stack the hours and also the billing totals, and want two Y axis, one for hours, the other for dollars.
I have got as far as this code, but it does not stack the hours or the invoiced amounts for each month. Also, I cannot seem to format either axis and the values in the labels to time and currency.
Is there an example you can point me to showing this. Thanks!
var barChartData = {
labels: ["January", "February", "March"],
datasets: [{
type: 'bar',
label: 'Billed Hours',
backgroundColor: "rgba(220,220,220,0.5)",
yAxisID: "y-axis-1",
data: [33.56, 68.45, 79.35]
}, {
type: 'bar',
label: 'Non Billed Hours',
backgroundColor: "rgba(222,220,220,0.5)",
yAxisID: "y-axis-1",
data: [3.50, 8.58, 7.53]
}, {
type: 'bar',
label: 'Income',
backgroundColor: "rgba(151,187,205,0.5)",
yAxisID: "y-axis-2",
data: [3800.00, 7565.65, 8500.96]
}, {
type: 'bar',
label: 'Income',
backgroundColor: "rgba(155,187,205,0.5)",
yAxisID: "y-axis-2",
data: [320.00, 780.65, 850.96]
}]
};
var ctx = document.getElementById("projectHours").getContext("2d");
window.myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
responsive: true,
hoverMode: 'label',
hoverAnimationDuration: 400,
stacked: true,
title: {
display: true,
text: "Billed / Billable Project Summary"
},
scales: {
yAxes: [{
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: "left",
id: "y-axis-1",
}, {
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: "right",
id: "y-axis-2",
gridLines: {
drawOnChartArea: false
},
}],
},
animation: {
onComplete: function () {
var ctx = this.chart.ctx;
ctx.textAlign = "center";
Chart.helpers.each(this.data.datasets.forEach(function (dataset) {
Chart.helpers.each(dataset.metaData.forEach(function (bar, index) {
ctx.fillText(dataset.data[index], bar._model.x, bar._model.y - 10);
}),this)
}),this);
}
}
}
});

You can extend the bar chart to do this
Preview
Script
Chart.defaults.groupableBar = Chart.helpers.clone(Chart.defaults.bar);
var helpers = Chart.helpers;
Chart.controllers.groupableBar = Chart.controllers.bar.extend({
calculateBarX: function (index, datasetIndex) {
// position the bars based on the stack index
var stackIndex = this.getMeta().stackIndex;
return Chart.controllers.bar.prototype.calculateBarX.apply(this, [index, stackIndex]);
},
// hide preceding datasets in groups other than the one we are in
hideOtherStacks: function (datasetIndex) {
var meta = this.getMeta();
var stackIndex = meta.stackIndex;
this.hiddens = [];
for (var i = 0; i < datasetIndex; i++) {
var dsMeta = this.chart.getDatasetMeta(i);
if (dsMeta.stackIndex !== stackIndex) {
this.hiddens.push(dsMeta.hidden);
dsMeta.hidden = true;
}
}
},
// reverse hideOtherStacks
unhideOtherStacks: function (datasetIndex) {
var meta = this.getMeta();
var stackIndex = meta.stackIndex;
for (var i = 0; i < datasetIndex; i++) {
var dsMeta = this.chart.getDatasetMeta(i);
if (dsMeta.stackIndex !== stackIndex) {
dsMeta.hidden = this.hiddens.unshift();
}
}
},
// we hide preceding datasets in groups other than the one we are in
// we then rely on the normal stacked logic to do its magic
calculateBarY: function (index, datasetIndex) {
this.hideOtherStacks(datasetIndex);
var barY = Chart.controllers.bar.prototype.calculateBarY.apply(this, [index, datasetIndex]);
this.unhideOtherStacks(datasetIndex);
return barY;
},
// similar to calculateBarY
calculateBarBase: function (datasetIndex, index) {
this.hideOtherStacks(datasetIndex);
var barBase = Chart.controllers.bar.prototype.calculateBarBase.apply(this, [datasetIndex, index]);
this.unhideOtherStacks(datasetIndex);
return barBase;
},
getBarCount: function () {
var stacks = [];
// put the stack index in the dataset meta
Chart.helpers.each(this.chart.data.datasets, function (dataset, datasetIndex) {
var meta = this.chart.getDatasetMeta(datasetIndex);
if (meta.bar && this.chart.isDatasetVisible(datasetIndex)) {
var stackIndex = stacks.indexOf(dataset.stack);
if (stackIndex === -1) {
stackIndex = stacks.length;
stacks.push(dataset.stack);
}
meta.stackIndex = stackIndex;
}
}, this);
this.getMeta().stacks = stacks;
return stacks.length;
},
});
and then
...
type: 'groupableBar',
options: {
scales: {
yAxes: [{
ticks: {
// we have to set this manually (or we could calculate it from our input data)
max: 160,
},
stacked: true,
}]
}
}
});
Note that we don't have any logic to set the y axis limits, we just hard code it. If you leave it unspecified, you'll end up with the limits you get if all the bars were stacked in one group.
Fiddle - http://jsfiddle.net/4rjge8sk/

Related

Chart JS custom message on tooltip, not x and y axis

I am displaying a bar chart that has 3 different pieces of information, (project name, number of days remaining, and the end date.) I am displaying the project name on one axis, and the number of days remaining determines the height of the bar. Currently, when I hover over a bar the tooltip displays the information already on the x and y axis. I want it to instead have the end date.
ie: project "b" will end in 2 days (August 4th), when I hover over the bar I want the tooltip to say "End date of 2022-08-04" instead of "b Work Days Remaining: 2"
My json of the data looks like this:
[{"po_num": "a", "days_rem": 10, "date_end": "2022-08-16"},
{"po_num": "b", "days_rem": 2, "date_end": "2022-08-04"},
{"po_num": "c", "days_rem": 6, "date_end": "2022-08-10"}]
Here is the link of the current graph.
https://i.stack.imgur.com/HefRz.png
Here is an MS paint rendering of what I am trying to do:
https://i.stack.imgur.com/GAT2I.png
The implementation code:
link = "{{{BASE_BACK_URL}}}";
$.getJSON(link, function (data) {
let po_names = [];
let days_rem = [];
for (let i = 0; i < data.length; i++) {
po_names.push(data[i]["po_num"]);
days_rem.push(data[i]["days_rem"]);
}
const ctx = document.getElementById('po-timeline-chart');
const myChart = new Chart(ctx, {
type: 'horizontalBar',
data: {
labels: po_names,
datasets: [{
label: 'Work Days Remaining',
data: days_rem,
backgroundColor: 'rgb(0, 89, 178)'
}],
},
options: {
legend: {
align: "end"
},
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
});
Solution listed below:
$.getJSON(link, function (data) {
let po_names = [];
let days_rem = [];
for (let i = 0; i < data.length; i++) {
po_names.push(data[i]["po_num"]);
days_rem.push(data[i]["days_rem"]);
}
const ctx = document.getElementById("po-timeline-chart");
const myChart = new Chart(ctx, {
type: "horizontalBar",
data: {
labels: po_names,
datasets: [
{
label: "Work Days Remaining",
data: days_rem,
backgroundColor: "rgb(0, 89, 178)",
},
],
},
options: {
tooltips: {
enabled: true,
callbacks: {
// To change title in tooltip
title: (data) => {
return "This PO will run out on";
},
// To change label in tooltip
label: (data) => {
return date_end[data['index']];
},
},
},
legend: {
align: "end",
},
scales: {
xAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
},
},
});
});

How to fix overflow data labels in graph created with Chart.js?

I have a graph created with Chart.js. There are options and one of them 'responsive: true' that provides a responsive view. The problem is when I load a graph with data the first time the y-ax labels overflow border and show as on the screen below. When I change the view y-ax labels show with overflow hidden and elepsis at the end of the label.
Also, I need to add a custom baloon for labels, how can I do it?
Before view change:
After view change:
Here is my chank of code:
drawWordsChart: function(placeholder, data, options = {}) {
console.log('drawWordsChart', data);
var sortable = [];
for (var word in data) {
sortable.push([data[word].text, data[word].weight]);
}
sortable.sort(function(a, b) {
return b[1] - a[1];
});
sortable = sortable.slice(0, 20);
let labels = [];
let values = [];
let colors = [], intense = 1;
angular.forEach(sortable, (elem, key) => {
colors.push('rgb(30, 144, 255,' + (intense - key / 20) + ')');
labels.push(elem[0]);
values.push(elem[1]);
});
var horizontalBarChartData = {
labels: labels,
datasets: [{
label: options.label || 'weight',
backgroundColor: colors,
borderColor: colors,
data: values
}]
};
const ctx = document.getElementById(placeholder).getContext('2d');
const myHorizontalBar = new Chart(ctx, {
type: options.type || 'horizontalBar',
data: horizontalBarChartData,
options: {
elements: {
rectangle: {
borderWidth: 1,
}
},
responsive: true,
legend: {
position: 'right',
display: false
},
scales: {
yAxes: [{
barPercentage: 0.1,
barThickness: 10,
maxBarThickness: 10,
minBarLength: 2,
gridLines: {
offsetGridLines: true
},
ticks: {
callback: function(value, index, values) {
return $filter('limitTo')(value, 8) + (value.length > 8 ? '...' : '');
}
}
}]
},
maintainAspectRatio: false
}
});
return myHorizontalBar;
}
Here I added property 'ticks' in options with callback, which limiting value to 8 letters, and add ellipsis at the end. Also, I added a custom filter.
ticks: {
callback: function(value, index, values) {
return $filter('limitTo')(value, 8) + (value.length > 8 ? '...' : '');
}
}

Chart js legend are being cut off if the bar height is equal to port height - chart js

I am using chart js to display barchart as :
$(function(){
let aid;
let $radio_input;
let none_obs;
let display = true;
let $js_dom_array = ["76.44", "120.00"];
let $js_am_label_arr = ["None $0", "Terrace - Large $2000"];
if($js_am_label_arr.length > 20){
display = false;
}
let $js_backgroundColor = ["rgba(26,179,148,0.5)", "rgba(26,179,148,0.5)"];
// let $div = document.getElementById("barChart");
// $div.height="140";
let ctx2 = document.getElementById("barChart").getContext("2d");
let chart = new Chart(ctx2, {
type: 'bar',
data: {
labels: $js_am_label_arr,
datasets: [{
label: 'DOM',
data: $js_dom_array,
backgroundColor: $js_backgroundColor,
barPercentage: 0.4,
maxBarThickness: 50,
// maxBarLength: 5,
}]
},
options: {
legend: {
display: false
},
responsive: true,
maintainAspectRatio: false,
legendCallback: function(chart) {
var text = [];
for (var i=0; i<chart.data.datasets.length; i++) {
text.push(chart.data.labels[i]);
}
return text.join("");
},
tooltips: {
mode: 'index',
callbacks: {
// Use the footer callback to display the sum of the items showing in the tooltip
title: function(tooltipItem, data) {
let title_str = data['labels'][tooltipItem[0]['index']];
// let lastIndex = title_str.lastIndexOf(" ");
// return title_str.substring(0, lastIndex);
return title_str;
},
label: function(tooltipItem, data) {
return 'Avg. DOM: '+data['datasets'][0]['data'][tooltipItem['index']];
},
},
},
scales: {
xAxes: [{
stacked: false,
beginAtZero: true,
// scaleLabel: {
// labelString: 'Month'
// },
ticks: {
display: display,
min: 0,
autoSkip: false,
maxRotation: 60,
callback: function(label, index, labels) {
// let lastIndex = label.lastIndexOf(" ");
// let avg_amount = label.split(" ").pop();
// let am_name = label.substring(0, lastIndex);
// let truncated_am_name = am_name.length > 30 ? (am_name.substring(0, 30)+'...') : am_name;
// return truncated_am_name+' '+avg_amount;
return label;
}
}
}]
},
layout: {
margin: {
top: 5
}
},
},
plugins:[{
afterDatasetsDraw: function(chart,options) {
// var chartInstance = chart,
let ctx = chart.ctx;
ctx.font = Chart.defaults.global.defaultFontStyle;
ctx.fillStyle = Chart.defaults.global.textColor;
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
chart.data.datasets.forEach(function (dataset, i) {
var meta = chart.controller.getDatasetMeta(i);
meta.data.forEach(function (bar, index) {
ctx.fillText(Math.round(dataset.data[index]), bar._model.x, bar._model.y); //bar._model.y - 5
});
})
}
}]
});
document.getElementById('barChart').innerHTML = chart.generateLegend();
})
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.3"></script>
<div style="height:400px;">
<canvas id="barChart" xheight="140px"></canvas>
</div>
If you need jsfiddle
Here, the value of second barchart is 120 and it is being cut off. I could pull text little down as: ctx.fillText(Math.round(dataset.data[index]), bar._model.x, bar._model.y + 5); But I don't wat the value to be overlapped with the bar. I have also tried with following options
layout: {
margin: {
top: 5
}
},
and
axisY:{
viewportMaximum: 130
},
But, none of these seems to work. Is there any way to increase the height or viewport of the chart js? It would be helpful if you could provide the js fiddle as well.
Instead of layout.margin.top, you need to define layout.padding.top as follows:
layout: {
padding: {
top: 20
}
},

multiple charts js in page but with same tooltips (about last chart)

I have more doughnut charts in one page, every chart have different data but I show the same tooltips. It's tooltips of the last chart. I don't found the problem.
This is js code:
var idList = [];
// --------------------
// Memo ID list...
// --------------------
jQuery('.idKQI').each(function (i) {
idList.push( jQuery(this).text() );
});
var idListLength = idList.length;
// ------------------
// Doughnut loop...
// ------------------
var dataDoughnutChart = {
labels: [
'KO',
'OK'
],
datasets: [{
data: [30,70],
backgroundColor: [
'#DF0101', // red
'#31B404' // green
]
}]
};
var optionsDoughnutChart = {
maintainAspectRatio: false,
responsive: true,
legend: {
display: false
},
tooltips: {
mode: 'dataset'
}
};
var idLav;
var ctxDoughnut;
var labelAdd;
var errati;
var esatti;
for (var i = 0, max = idListLength; i < max; i++) {
idLav = '#' + idList[i] + "_chartDoughnut";
ctxDoughnut = jQuery(idLav);
labelAdd = jQuery(idLav).data("labeladd");
errati = jQuery(idLav).data("errati");
esatti = jQuery(idLav).data("esatti");
dataDoughnutChart.labels[0] = 'Errati' + labelAdd;
dataDoughnutChart.labels[1] = 'Esatti' + labelAdd;
dataDoughnutChart.datasets[0].data[0] = errati;
dataDoughnutChart.datasets[0].data[1] = esatti;
var myDoughnutChart = new Chart(ctxDoughnut, {
type: 'doughnut',
data: dataDoughnutChart,
options: optionsDoughnutChart
});
}
If I have two doughnut chart, in witch in the first chart datasets.data = [10,90], and in the second chart datasets.data = [2,98], the tooltips for all two chart show 'Errati: 2' and 'Esatti: 98'. It's values like the second chart.
I'm also try to use an array for var dataDoughnutChart like:
var myDoughnutChart = new Chart(ctxDoughnut, {
type: 'doughnut',
data: dataDoughnutChart[i],
options: optionsDoughnutChart
});
but don't resolve.
Thanks for your help.
Resolved like below:
// .....
configDoughnutList.push(
{
type: 'doughnut',
data: {
datasets: [{
data: [
30,
70
],
backgroundColor: [
'#DF0101', // rosso
'#31B404' // verde
],
label: 'daughnut_163'
}],
labels: [
'Errati',
'Corretti'
]
},
options: {
responsive: true,
legend: {
display: false
},
animation: {
animateScale: true,
animateRotate: true
},
tooltips: {
mode: 'dataset'
}
}
}
);
configDoughnutList[i].data.datasets[0].data[0] = errati;
configDoughnutList[i].data.datasets[0].data[1] = esatti;
configDoughnutList[i].data.labels[0] = 'Errati' + labelAdd;
configDoughnutList[i].data.labels[1] = 'Esatti' + labelAdd;
window.myDoughnut = new Chart(ctxDoughnut, configDoughnutList[i]);

ChartJS New Lines '\n' in X axis Labels or Displaying More Information Around Chart or Tooltip with ChartJS V2

I'm using chart.js (V2) to try to build a bar chart that has more information available to user without having to hover over or click anywhere. I've provided two examples of how I hope to edit my chart.
Two edited versions of what I hope to achieve
As can be seen, I hope to place (somewhere), some extra information outside of the labels. I had hope that by adding '\n' to the labels I might have been able to get what I was looking for similar to option A.
Some edited code is provided blow:
var barChartData = {
labels: playerNames,
datasets: [{
label: 'Actual Score/Hour',
backgroundColor: "rgba(0, 128, 0,0.5)",
data: playerScores
}, {
label: 'Expected Score/Hour',
backgroundColor: "rgba(255,0,0,0.5)",
data: playerExpected
}]
};
function open_win(linktosite) {
window.open(linktosite)
}
canvas.onclick = function(evt){
var activePoints = myBar.getElementsAtEvent(evt);
console.log(activePoints);
linktosite = 'https://www.mytestsite.com/' + activePoints[1]['_model']['label'];
open_win(linktosite);
};
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
title:{
display:true,
text:"Player Expected and Actual Score per Hour"
},
tooltips: {
mode: 'label'
},
responsive: true,
scales: {
xAxes: [{
stacked: false,
}],
yAxes: [{
stacked: false
}]
},
animation: {
onComplete: function () {
var ctx = this.chart.ctx;
ctx.textAlign = "center";
Chart.helpers.each(this.data.datasets.forEach(function (dataset) {
Chart.helpers.each(dataset.metaData.forEach(function (bar, index) {
// console.log("printing bar" + bar);
ctx.fillText(dataset.data[index], bar._model.x, bar._model.y - 10);
}),this)
}),this);
}
}
}
});
// Chart.helpers.each(myBar.getDatasetMeta(0).data, function(rectangle, index) {
// rectangle.draw = function() {
// myBar.chart.ctx.setLineDash([5, 5]);
// Chart.elements.Rectangle.prototype.draw.apply(this, arguments);
// }
// }, null);
};
At this point I'd be satisfied with having the extradata anywhere on the bar. Any help would be appreciated. Thanks~
Chart.js v2.1.5 allows for multi-line labels using nested arrays (v2.5.0 fixes it for radar graphs):
...
data: {
labels: [["Jake", "Active: 2 hrs", "Score: 1", "Expected: 127", "Attempts: 4"],
["Matt", "Active: 2 hrs", "Score: 4", "Expected: 36", "Attempts: 4"]],
...
However, this does mean that you will have to pre-calculate the label values.
var config = {
type: 'line',
data: {
labels: [["January","First Month","Jellyfish","30 of them"], ["February","Second Month","Foxes","20 of them"], ["March","Third Month","Mosquitoes","None of them"], "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
data: [65, 40, 80, 81, 56, 85, 45],
backgroundColor: "rgba(255,99,132,0.2)",
}, {
label: "My Second dataset",
data: [40, 80, 21, 56, 85, 45, 65],
backgroundColor: "rgba(99,255,132,0.2)",
}]
},
scales : {
xAxes : [{
gridLines : {
display : false,
lineWidth: 1,
zeroLineWidth: 1,
zeroLineColor: '#666666',
drawTicks: false
},
ticks: {
display:true,
stepSize: 0,
min: 0,
autoSkip: false,
fontSize: 11,
padding: 12
}
}],
yAxes: [{
ticks: {
padding: 5
},
gridLines : {
display : true,
lineWidth: 1,
zeroLineWidth: 2,
zeroLineColor: '#666666'
}
}]
},
spanGaps: true,
responsive: true,
maintainAspectRatio: true
};
var ctx = document.getElementById("myChart").getContext("2d");
new Chart(ctx, config);
<div class="myChart">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js"></script>
<canvas id="myChart"></canvas>
</div>
If a label is an array as opposed to a string i.e. [["June","2015"], "July"] then each element is treated as a separate line. The appropriate calculations are made to determine the correct height and width, and rotation is still supported.
charJS version 2.7.2 used
this also works in https://github.com/jtblin/angular-chart.js
If you are using Chart.js v2.7.1, the above solution might not work.
The solution that actually worked for us was adding a small plugin right in the data and options level:
const config = {
type: 'bar',
data: {
// ...
},
options: {
// ...
},
plugins: [{
beforeInit: function (chart) {
chart.data.labels.forEach(function (label, index, labelsArr) {
if (/\n/.test(label)) {
labelsArr[index] = label.split(/\n/)
}
})
}
}]
};
A full description of how to fix this issue can be found here.
With Chart.js v2.1, you can write a chart plugin to do this
Preview
Script
Chart.pluginService.register({
beforeInit: function (chart) {
var hasWrappedTicks = chart.config.data.labels.some(function (label) {
return label.indexOf('\n') !== -1;
});
if (hasWrappedTicks) {
// figure out how many lines we need - use fontsize as the height of one line
var tickFontSize = Chart.helpers.getValueOrDefault(chart.options.scales.xAxes[0].ticks.fontSize, Chart.defaults.global.defaultFontSize);
var maxLines = chart.config.data.labels.reduce(function (maxLines, label) {
return Math.max(maxLines, label.split('\n').length);
}, 0);
var height = (tickFontSize + 2) * maxLines + (chart.options.scales.xAxes[0].ticks.padding || 0);
// insert a dummy box at the bottom - to reserve space for the labels
Chart.layoutService.addBox(chart, {
draw: Chart.helpers.noop,
isHorizontal: function () {
return true;
},
update: function () {
return {
height: this.height
};
},
height: height,
options: {
position: 'bottom',
fullWidth: 1,
}
});
// turn off x axis ticks since we are managing it ourselves
chart.options = Chart.helpers.configMerge(chart.options, {
scales: {
xAxes: [{
ticks: {
display: false,
// set the fontSize to 0 so that extra labels are not forced on the right side
fontSize: 0
}
}]
}
});
chart.hasWrappedTicks = {
tickFontSize: tickFontSize
};
}
},
afterDraw: function (chart) {
if (chart.hasWrappedTicks) {
// draw the labels and we are done!
chart.chart.ctx.save();
var tickFontSize = chart.hasWrappedTicks.tickFontSize;
var tickFontStyle = Chart.helpers.getValueOrDefault(chart.options.scales.xAxes[0].ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
var tickFontFamily = Chart.helpers.getValueOrDefault(chart.options.scales.xAxes[0].ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
var tickLabelFont = Chart.helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
chart.chart.ctx.font = tickLabelFont;
chart.chart.ctx.textAlign = 'center';
var tickFontColor = Chart.helpers.getValueOrDefault(chart.options.scales.xAxes[0].fontColor, Chart.defaults.global.defaultFontColor);
chart.chart.ctx.fillStyle = tickFontColor;
var meta = chart.getDatasetMeta(0);
var xScale = chart.scales[meta.xAxisID];
var yScale = chart.scales[meta.yAxisID];
chart.config.data.labels.forEach(function (label, i) {
label.split('\n').forEach(function (line, j) {
chart.chart.ctx.fillText(line, xScale.getPixelForTick(i + 0.5), (chart.options.scales.xAxes[0].ticks.padding || 0) + yScale.getPixelForValue(yScale.min) +
// move j lines down
j * (chart.hasWrappedTicks.tickFontSize + 2));
});
});
chart.chart.ctx.restore();
}
}
});
and then
...
data: {
labels: ["January\nFirst Month\nJellyfish\n30 of them", "February\nSecond Month\nFoxes\n20 of them", "March\nThird Month\nMosquitoes\nNone of them", "April", "May", "June", "July"],
...
Note - we assume that the maximum content of one line will fit between the ticks (i.e. that no rotation logic is needed. I'm sure it's possible to incorporate rotation logic too, but it would be a tad more complicated)
You should format the tooltips to not show the x axis label, or format it to show a shorter version of the label.
Fiddle - http://jsfiddle.net/m0q03wpy/

Categories

Resources