web-dev-qa-db-fra.com

Nouvelles lignes ChartJS '\ n' dans les étiquettes de l'axe X ou affichage d'informations supplémentaires autour d'un graphique ou d'une info-bulle avec ChartJS V2

J'utilise chart.js (V2) pour essayer de créer un graphique à barres contenant davantage d'informations à la disposition de l'utilisateur, sans avoir à survoler ou cliquer n'importe où. J'ai fourni deux exemples de la manière dont j'espère modifier mon graphique.

Deux versions éditées de ce que j'espère réaliser

Comme on peut le constater, j'espère placer (quelque part) des informations supplémentaires en dehors des étiquettes. J'espérais qu'en ajoutant '\ n' aux étiquettes, j'aurais pu obtenir ce que je cherchais, comme pour l'option A. 

Certains codes édités sont fournis coup:

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);            
    };

À ce stade, je serais satisfait d'avoir l'extradata n'importe où dans le bar. Toute aide serait appréciée. Merci ~ 

11
user3878014

Chart.js v2.1.5 autorise les étiquettes multilignes utilisant des tableaux imbriqués (la version 2.5.0 le corrige pour les graphiques radar):

...
data: {
    labels: [["Jake", "Active: 2 hrs", "Score: 1", "Expected: 127", "Attempts: 4"], 
             ["Matt", "Active: 2 hrs", "Score: 4", "Expected: 36", "Attempts: 4"]],
    ...

Toutefois, cela signifie que vous devrez pré-calculer les valeurs de l'étiquette.

18
Chris Trevarthen

Avec Chart.js v2.1, vous pouvez écrire un plugin graphique pour le faire.


Aperçu

 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();
        }
    }
});

et alors

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

Remarque: nous supposons que le contenu maximal d’une ligne s’adaptera entre les graduations (c’est-à-dire qu’aucune logique de rotation n’est nécessaire. Je suis sûr qu’il est possible d’incorporer la logique de rotation également, mais ce serait un peu plus compliqué).

Vous devez formater les info-bulles pour ne pas afficher l’étiquette de l’axe des x ou le formater pour en afficher une version plus courte.


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

5
potatopeelings

Si vous utilisez Chart.js v2.7.1, la solution ci-dessus risque de ne pas fonctionner.

La solution qui a réellement fonctionné pour nous a été l’ajout d’un petit droit plugin aux niveaux data et options:

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/)
        }
      })
    }
  }]
};

Vous trouverez une description complète de la procédure à suivre pour résoudre ce problème ici .

4
iorrah

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>

Si une étiquette est un tableau par opposition à une chaîne, c'est-à-dire [["juin", "2015"], "juillet"], chaque élément est traité comme une ligne distincte. Les calculs appropriés sont effectués pour déterminer la hauteur et la largeur correctes, et la rotation est toujours prise en charge. 

charJS version 2.7.2 utilisé cela fonctionne aussi dans https://github.com/jtblin/angular-chart.js

1
SSD