ChartJS New Lines '\ n' along the X axis Shortcuts or display additional information Around the chart or tooltip with ChartJS V2

I use chart.js (V2) to try and build a histogram that has more information available to the user, without having to hover over it or click anywhere. I presented two examples of how I hope to change my chart.

Two edited versions of what I hope to achieve

As you can see, I hope to place (somewhere) additional information outside the labels. I was hoping that by adding '\ n' to the shortcuts, I could get what I was looking for, similar to option A.

Some edited codes get hit:

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 would be pleased to have extradata anywhere on the panel. Any help would be greatly appreciated. Thanks ~

+8
source share
4 answers

Chart.js v2.1.5 allows the use of multi-line labels using nested arrays (v2.5.0 fixes this 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 means that you have to pre-calculate the label values.

+11
source

With Chart.js v2.1 you can write a chart plugin for this


Preview

enter image description here


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 correspond between ticks (i.e. that no rotation logic is required. I am sure it is also possible to enable rotation logic, but it will be a little more complicated)

You must format tooltips to not show the x-axis label, or format it to show a shorter version of the label.


Fiddle - http://jsfiddle.net/m0q03wpy/

+3
source

If you are using Chart.js v2.7.1, the above solution may not work.

The solution that actually worked for us was to add a small plugin to the right at the data and options level:

 const config = { type: 'bar', data: { // ... }, options: { // ... }, plugins: [{ beforeInit: function (chart) { chart.data.labels.forEach(function (e, i, a) { if (/\n/.test(e)) { a[i] = e.split(/\n/) } }) } }] }; 

A full description of how to fix this problem can be found here .

+1
source

 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 the label is an array, not a string, that is, [["June", "2015"], "July"], then each element is treated as a separate line. Appropriate calculations are performed to determine the correct height and width, and rotation is still supported.

Is used

charJS version 2.7.2 this also works at https://github.com/jtblin/angular-chart.js

0
source

Source: https://habr.com/ru/post/1012769/


All Articles