Comment ajouter du texte dans le graphique en anneau à l'aide de Chart.js?

Réponses:

36

Vous devez modifier le code comme: dans chart.Doughnut.defaults

labelFontFamily : "Arial",
labelFontStyle : "normal",
labelFontSize : 24,
labelFontColor : "#666"

puis en fonction drawPieSegments

ctx.fillText(data[0].value + "%", width/2 - 20, width/2, 200);

Voir ce pull: https://github.com/nnnick/Chart.js/pull/35

voici un violon http://jsfiddle.net/mayankcpdixit/6xV78/ implémentant le même.

mayankcpdixit
la source
2
Y a-t-il quelqu'un d'autre qui ne trouve pas cette fonction drawPieSegments?
Yulian du
2
Il convient de mentionner que cela ne fonctionne pas avec la v2. Utilisez le code jsfiddle inclus pour une utilisation facile
Alwin Kesler
1
Comment ajouter le% dans une nouvelle ligne? est-ce pris en charge?
user7334203
1
C'est toujours la solution?
ACB
@ ArunC.B - faites défiler vers le bas
ashleedawg
176

Aucune des autres réponses ne redimensionne le texte en fonction de la quantité de texte et de la taille du beignet. Voici un petit script que vous pouvez utiliser pour placer dynamiquement n'importe quelle quantité de texte au milieu, et il le redimensionnera automatiquement.

Exemple: http://jsfiddle.net/kdvuxbtj/

Donut avec texte dynamique au milieu

Il faudra n'importe quelle quantité de texte dans la taille du beignet parfaite pour le beignet. Pour éviter de toucher les bords, vous pouvez définir un rembourrage latéral comme un pourcentage du diamètre de l'intérieur du cercle. Si vous ne le définissez pas, la valeur par défaut est 20. Vous avez également la couleur, la police et le texte. Le plugin s'occupe du reste.

Le code du plugin commencera avec une taille de police de base de 30px. De là, il vérifiera la largeur du texte et le comparera au rayon du cercle et le redimensionnera en fonction du rapport de largeur du cercle / texte.

Il a une taille de police minimale par défaut de 20 px. Si le texte dépasse les limites à la taille de police minimale, il encapsulera le texte. La hauteur de ligne par défaut lors de l'habillage du texte est de 25 px, mais vous pouvez la modifier. Si vous définissez la taille de police minimale par défaut sur false, le texte deviendra infiniment petit et ne sera pas enveloppé.

Il a également une taille de police maximale par défaut de 75px au cas où il n'y aurait pas assez de texte et que le lettrage serait trop grand.

Ceci est le code du plugin

Chart.pluginService.register({
  beforeDraw: function(chart) {
    if (chart.config.options.elements.center) {
      // Get ctx from string
      var ctx = chart.chart.ctx;

      // Get options from the center object in options
      var centerConfig = chart.config.options.elements.center;
      var fontStyle = centerConfig.fontStyle || 'Arial';
      var txt = centerConfig.text;
      var color = centerConfig.color || '#000';
      var maxFontSize = centerConfig.maxFontSize || 75;
      var sidePadding = centerConfig.sidePadding || 20;
      var sidePaddingCalculated = (sidePadding / 100) * (chart.innerRadius * 2)
      // Start with a base font of 30px
      ctx.font = "30px " + fontStyle;

      // Get the width of the string and also the width of the element minus 10 to give it 5px side padding
      var stringWidth = ctx.measureText(txt).width;
      var elementWidth = (chart.innerRadius * 2) - sidePaddingCalculated;

      // Find out how much the font can grow in width.
      var widthRatio = elementWidth / stringWidth;
      var newFontSize = Math.floor(30 * widthRatio);
      var elementHeight = (chart.innerRadius * 2);

      // Pick a new font size so it will not be larger than the height of label.
      var fontSizeToUse = Math.min(newFontSize, elementHeight, maxFontSize);
      var minFontSize = centerConfig.minFontSize;
      var lineHeight = centerConfig.lineHeight || 25;
      var wrapText = false;

      if (minFontSize === undefined) {
        minFontSize = 20;
      }

      if (minFontSize && fontSizeToUse < minFontSize) {
        fontSizeToUse = minFontSize;
        wrapText = true;
      }

      // Set font settings to draw it correctly.
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      var centerX = ((chart.chartArea.left + chart.chartArea.right) / 2);
      var centerY = ((chart.chartArea.top + chart.chartArea.bottom) / 2);
      ctx.font = fontSizeToUse + "px " + fontStyle;
      ctx.fillStyle = color;

      if (!wrapText) {
        ctx.fillText(txt, centerX, centerY);
        return;
      }

      var words = txt.split(' ');
      var line = '';
      var lines = [];

      // Break words up into multiple lines if necessary
      for (var n = 0; n < words.length; n++) {
        var testLine = line + words[n] + ' ';
        var metrics = ctx.measureText(testLine);
        var testWidth = metrics.width;
        if (testWidth > elementWidth && n > 0) {
          lines.push(line);
          line = words[n] + ' ';
        } else {
          line = testLine;
        }
      }

      // Move the center up depending on line height and number of lines
      centerY -= (lines.length / 2) * lineHeight;

      for (var n = 0; n < lines.length; n++) {
        ctx.fillText(lines[n], centerX, centerY);
        centerY += lineHeight;
      }
      //Draw text in center
      ctx.fillText(line, centerX, centerY);
    }
  }
});

Et vous utilisez les options suivantes dans votre objet graphique

options: {
  elements: {
    center: {
      text: 'Red is 2/3 the total numbers',
      color: '#FF6384', // Default is #000000
      fontStyle: 'Arial', // Default is Arial
      sidePadding: 20, // Default is 20 (as a percentage)
      minFontSize: 20, // Default is 20 (in px), set to false and text will not wrap.
      lineHeight: 25 // Default is 25 (in px), used for when text wraps
    }
  }
}

Merci à @Jenna Sloan pour l'aide avec les mathématiques utilisées dans cette solution.

Alesana
la source
5
Fonctionne très bien! La plupart des autres options sont interrompues lorsque la légende est à droite ou à gauche.
louisav
2
Solution géniale!
JustLooking
3
J'ai mis à jour votre violon et ajouté une taille de police maximale: jsfiddle.net/nkzyx50o/3059
Felix Geenen
4
Est-il possible de diviser le texte sur plusieurs lignes? Mon texte a 6 mots et il déborde entre les limites de la découpe
Quanda
2
Merci, cela fonctionne aussi pour moi, mais comment ajouter du texte sur plusieurs lignes?
Ashutosh Shrestha
54

Voici un exemple nettoyé et combiné des solutions ci-dessus - réactif (essayez de redimensionner la fenêtre), prend en charge l'auto-alignement de l'animation, prend en charge les info-bulles

https://jsfiddle.net/cmyker/u6rr5moq/

Chart.types.Doughnut.extend({
    name: "DoughnutTextInside",
    showTooltip: function() {
        this.chart.ctx.save();
        Chart.types.Doughnut.prototype.showTooltip.apply(this, arguments);
        this.chart.ctx.restore();
    },
    draw: function() {
        Chart.types.Doughnut.prototype.draw.apply(this, arguments);

        var width = this.chart.width,
            height = this.chart.height;

        var fontSize = (height / 114).toFixed(2);
        this.chart.ctx.font = fontSize + "em Verdana";
        this.chart.ctx.textBaseline = "middle";

        var text = "82%",
            textX = Math.round((width - this.chart.ctx.measureText(text).width) / 2),
            textY = height / 2;

        this.chart.ctx.fillText(text, textX, textY);
    }
});

var data = [{
    value: 30,
    color: "#F7464A"
}, {
    value: 50,
    color: "#E2EAE9"
}, {
    value: 100,
    color: "#D4CCC5"
}, {
    value: 40,
    color: "#949FB1"
}, {
    value: 120,
    color: "#4D5360"
}];

var DoughnutTextInsideChart = new Chart($('#myChart')[0].getContext('2d')).DoughnutTextInside(data, {
    responsive: true
});
<html>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
<body>
    <canvas id="myChart"></canvas>
</body>
</html>

MISE À JOUR 17.06.16:

Même fonctionnalité mais pour la version 2 de chart.js:

https://jsfiddle.net/cmyker/ooxdL2vj/

var data = {
  labels: [
    "Red",
    "Blue",
    "Yellow"
  ],
  datasets: [
    {
      data: [300, 50, 100],
      backgroundColor: [
        "#FF6384",
        "#36A2EB",
        "#FFCE56"
      ],
      hoverBackgroundColor: [
        "#FF6384",
        "#36A2EB",
        "#FFCE56"
      ]
    }]
};

Chart.pluginService.register({
  beforeDraw: function(chart) {
    var width = chart.chart.width,
        height = chart.chart.height,
        ctx = chart.chart.ctx;

    ctx.restore();
    var fontSize = (height / 114).toFixed(2);
    ctx.font = fontSize + "em sans-serif";
    ctx.textBaseline = "middle";

    var text = "75%",
        textX = Math.round((width - ctx.measureText(text).width) / 2),
        textY = height / 2;

    ctx.fillText(text, textX, textY);
    ctx.save();
  }
});

var chart = new Chart(document.getElementById('myChart'), {
  type: 'doughnut',
  data: data,
  options: {
  	responsive: true,
    legend: {
      display: false
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.bundle.js"></script>
<canvas id="myChart"></canvas>

Cmyker
la source
3
J'ai Uncaught TypeError: Cannot read property 'extend' of undefineddes idées?
Max Rose-Collins
2
Vous pouvez également modifier la couleur du texte en utilisant ctx.fillStyle = 'black';
Adrian Lopez
cela continue d'écrire sur le texte encore et encore si le graphique est actualisé en fournissant de nouveaux paramètres de données
techie_28
Avez-vous trouvé la solution pour cela?
Cmyker
@Cmyker, la solution CSS / HTML pourrait aider, mais cela n'exporte pas le texte central lorsque le graphique est exporté au format PNG.Des idées pour rectifier cela? C'était une solution complète, mais elle n'efface pas la zone centrale lorsque le graphique est actualisé .
techie_28
38

J'éviterais de modifier le code chart.js pour ce faire, car c'est assez facile avec du CSS et du HTML classiques. Voici ma solution:

HTML:

<canvas id="productChart1" width="170"></canvas>
<div class="donut-inner">
    <h5>47 / 60 st</h5>
    <span>(30 / 25 st)</span>
</div>

CSS:

.donut-inner {
   margin-top: -100px;
   margin-bottom: 100px;
}
.donut-inner h5 {
   margin-bottom: 5px;
   margin-top: 0;
}
.donut-inner span {
   font-size: 12px;
}

La sortie ressemble à ceci:

entrez la description de l'image ici

Mattias
la source
4
Pourquoi pas? Ajoutez simplement @ media-queries à vos cours.
Mattias
2
Cela ne fonctionne pas pour moi, j'utilise une manière réactive, donc je ne peux pas utiliser de valeurs fixes. :(
Massa
2
@Massa avez-vous essayé d'utiliser les requêtes média pour les différentes résolutions? Ou modifier le CSS que j'ai écrit pour utiliser% au lieu de px?
Mattias
2
@Mattias c'était une bonne solution mais le texte central n'est pas exporté lorsque le graphique est téléchargé au format PNG.
techie_28
1
@ techie_28 point valide, n'a pas pris cela en compte puisque la question ne mentionnait pas du tout l'exportation.
Mattias
20

Cela fonctionne aussi de mon côté ...

<div style="width: 100px; height: 100px; float: left; position: relative;">
    <div
        style="width: 100%; height: 40px; position: absolute; top: 50%; left: 0; margin-top: -20px; line-height:19px; text-align: center; z-index: 999999999999999">
        99%<Br />
        Total
    </div>
    <canvas id="chart-area" width="100" height="100" />
</div>

entrez la description de l'image ici

Amrik Singh
la source
4
J'ai utilisé votre solution parce que c'était la plus rapide et qu'elle fait son travail. Merci!
MDT
@Amrik Singh c'est une bonne solution en effet, mais le texte central ne sera pas exporté si le graphique est téléchargé sous forme d'image PNG.
techie_28
Belle solution, il ne faut pas beaucoup de peine.
Shashank
tu es mon mec! Je ne trouve pas de solution dans angularjs et je n'ai jamais fait comme ça. Incroyable.
Nomi Ali
1
solution charmante, rapide et propre
Khaleel
11

Base sur la réponse @ rap-2-h, voici le code pour utiliser le texte sur un graphique en anneau sur Chart.js pour une utilisation dans un tableau de bord comme. Il a une taille de police dynamique pour une option réactive.

HTML:

<div>text
<canvas id="chart-area" width="300" height="300" style="border:1px solid"/><div>

Scénario:

var doughnutData = [
            {
                value: 100,
                color:"#F7464A",
                highlight: "#FF5A5E",
                label: "Red"
            },
            {
                value: 50,
                color: "#CCCCCC",
                highlight: "#5AD3D1",
                label: "Green"
            }
        ];

$(document).ready(function(){
  var ctx = $('#chart-area').get(0).getContext("2d");

  var myDoughnut = new Chart(ctx).Doughnut(doughnutData,{
     animation:true,
     responsive: true,
     showTooltips: false,
     percentageInnerCutout : 70,
     segmentShowStroke : false,
     onAnimationComplete: function() {

     var canvasWidthvar = $('#chart-area').width();
     var canvasHeight = $('#chart-area').height();
     //this constant base on canvasHeight / 2.8em
     var constant = 114;
     var fontsize = (canvasHeight/constant).toFixed(2);
     ctx.font=fontsize +"em Verdana";
     ctx.textBaseline="middle"; 
     var total = 0;
     $.each(doughnutData,function() {
       total += parseInt(this.value,10);
   });
  var tpercentage = ((doughnutData[0].value/total)*100).toFixed(2)+"%";
  var textWidth = ctx.measureText(tpercentage).width;

   var txtPosx = Math.round((canvasWidthvar - textWidth)/2);
    ctx.fillText(tpercentage, txtPosx, canvasHeight/2);
  }
 });
});

Voici l'exemple de code.try pour redimensionner la fenêtre. http://jsbin.com/wapono/13/edit

Ztuons Ch
la source
1
Cela devrait être la réponse acceptée dans le cas d'un besoin de réactivité (mon cas).
Greg Blass
2
Si vous avez des info-bulles, le texte disparaît au survol.
Yulian du
Erreur "jQuery.Deferred exception: le graphique n'est pas défini"
Kiquenet
11

Vous pouvez utiliser css avec un positionnement relatif / absolu si vous le souhaitez réactif. De plus, il peut gérer facilement la multi-ligne.

https://jsfiddle.net/mgyp0jkk/

<div class="relative">
  <canvas id="myChart"></canvas>      
  <div class="absolute-center text-center">
    <p>Some text</p>
    <p>Some text</p>
  </div>
</div>
Dayze
la source
beautiful solution :)
Manza
Super travail frère tu as fait ma journée
DVP SmartCreators Inc nous faisons le
8

Ceci est basé sur la mise à jour de Cmyker pour Chart.js 2. (publiée comme une autre réponse car je ne peux pas encore commenter)

J'ai eu un problème avec l'alignement du texte sur Chrome lorsque la légende est affichée car la hauteur du graphique ne l'inclut pas, donc elle n'est pas correctement alignée au milieu. Correction de cela en tenant compte de cela dans le calcul de fontSize et textY.

J'ai calculé le pourcentage à l'intérieur de la méthode plutôt qu'une valeur définie car j'en ai plusieurs sur la page. L'hypothèse est que votre graphique n'a que 2 valeurs (sinon quel est le pourcentage de? Et que la première est celle pour laquelle vous voulez afficher le pourcentage. J'ai également un tas d'autres graphiques, donc je vérifie type = donut. J'utilise uniquement des beignets pour afficher les pourcentages, donc cela fonctionne pour moi.

La couleur du texte semble un peu hasardeuse en fonction de l'ordre dans lequel les choses se déroulent, etc., donc j'ai rencontré un problème lors du redimensionnement selon lequel le texte changerait de couleur (entre le noir et la couleur principale dans un cas, et la couleur secondaire et le blanc dans un autre). Je "sauvegarde" quel que soit le style de remplissage existant, dessine le texte (dans la couleur des données primaires) puis restaure l'ancien style de remplissage. (La préservation de l'ancien style de remplissage ne semble pas nécessaire, mais on ne sait jamais.)

https://jsfiddle.net/g733tj8h/

Chart.pluginService.register({
  beforeDraw: function(chart) {
    var width = chart.chart.width,
        height = chart.chart.height,
        ctx = chart.chart.ctx,
        type = chart.config.type;

    if (type == 'doughnut')
    {
      var percent = Math.round((chart.config.data.datasets[0].data[0] * 100) /
                    (chart.config.data.datasets[0].data[0] +
                    chart.config.data.datasets[0].data[1]));
      var oldFill = ctx.fillStyle;
      var fontSize = ((height - chart.chartArea.top) / 100).toFixed(2);

      ctx.restore();
      ctx.font = fontSize + "em sans-serif";
      ctx.textBaseline = "middle"

      var text = percent + "%",
          textX = Math.round((width - ctx.measureText(text).width) / 2),
          textY = (height + chart.chartArea.top) / 2;

      ctx.fillStyle = chart.config.data.datasets[0].backgroundColor[0];
      ctx.fillText(text, textX, textY);
      ctx.fillStyle = oldFill;
      ctx.save();
    }
  }
});

Rory
la source
7

Vous pouvez également coller le code de mayankcpdixit dans l' onAnimationCompleteoption:

// ...
var myDoughnutChart = new Chart(ctx).Doughnut(data, {
    onAnimationComplete: function() {
        ctx.fillText(data[0].value + "%", 100 - 20, 100, 200);
    }
});

Le texte sera affiché après l'animation

rap-2-h
la source
6
Bon mais le texte disparaît en
survol
1
Correct, le texte disparaît au survol ... :( Ce serait génial si le texte n'a pas disparu, aucune idée de comment faire cela? Merci
MDT
@MDT @maud peut être en utilisant la saveméthode
techie_28
7

Je crée une démo avec 7 jQueryUI Slider et ChartJs (avec du texte dynamique à l'intérieur)

Chart.types.Doughnut.extend({
        name: "DoughnutTextInside",
        showTooltip: function() {
            this.chart.ctx.save();
            Chart.types.Doughnut.prototype.showTooltip.apply(this, arguments);
            this.chart.ctx.restore();
        },
        draw: function() {
            Chart.types.Doughnut.prototype.draw.apply(this, arguments);

            var width = this.chart.width,
                height = this.chart.height;

            var fontSize = (height / 140).toFixed(2);
            this.chart.ctx.font = fontSize + "em Verdana";
            this.chart.ctx.textBaseline = "middle";

            var red = $( "#red" ).slider( "value" ),
            green = $( "#green" ).slider( "value" ),
            blue = $( "#blue" ).slider( "value" ),
            yellow = $( "#yellow" ).slider( "value" ),
            sienna = $( "#sienna" ).slider( "value" ),
            gold = $( "#gold" ).slider( "value" ),
            violet = $( "#violet" ).slider( "value" );
            var text = (red+green+blue+yellow+sienna+gold+violet) + " minutes";
            var textX = Math.round((width - this.chart.ctx.measureText(text).width) / 2);
            var textY = height / 2;
            this.chart.ctx.fillStyle = '#000000';
            this.chart.ctx.fillText(text, textX, textY);
        }
    });


var ctx = $("#myChart").get(0).getContext("2d");
var myDoughnutChart = new Chart(ctx).DoughnutTextInside(data, {
    responsive: false
});

DÉMO DANS JSFIDDLE

entrez la description de l'image ici

Stéphane GRILLON
la source
3

La réponse de @ rap-2-h et @Ztuons Ch ne permet pas à l' showTooltipsoption d'être active, mais ce que vous pouvez faire est de créer et de superposer un deuxième canvasobjet derrière celui qui rend le graphique.

La partie importante est le style requis dans les divs et pour l'objet canvas lui-même afin qu'ils s'affichent les uns sur les autres.

var data = [
    {value : 100, color : 'rgba(226,151,093,1)', highlight : 'rgba(226,151,093,0.75)', label : "Sector 1"},
    {value : 100, color : 'rgba(214,113,088,1)', highlight : 'rgba(214,113,088,0.75)', label : "Sector 2"},
    {value : 100, color : 'rgba(202,097,096,1)', highlight : 'rgba(202,097,096,0.75)', label : "Sector 3"}
]

var options = { showTooltips : true };
     
var total = 0;
for (i = 0; i < data.length; i++) {
     total = total + data[i].value;
}

var chartCtx = $("#canvas").get(0).getContext("2d");
var chart = new Chart(chartCtx).Doughnut(data, options);

var textCtx = $("#text").get(0).getContext("2d");
textCtx.textAlign = "center";
textCtx.textBaseline = "middle";
textCtx.font = "30px sans-serif";
textCtx.fillText(total, 150, 150);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
<html>
<body>
<div style="position: relative; width:300px; height:300px;">
    <canvas id="text" 
            style="z-index: 1; 
                   position: absolute;
                   left: 0px; 
                   top: 0px;" 
            height="300" 
            width="300"></canvas>
    <canvas id="canvas" 
            style="z-index: 2; 
                   position: absolute;
                   left: 0px; 
                   top: 0px;" 
            height="300" 
            width="300"></canvas>
</div>
</body>
</html>

Voici le jsfiddle: https://jsfiddle.net/68vxqyak/1/

RYUUSEiiSTAR
la source
1

@Cmyker, excellente solution pour chart.js v2

Une petite amélioration: il est logique de vérifier l'ID de canevas approprié, voir l'extrait de code modifié ci-dessous. Sinon, le texte (c'est-à-dire 75%) est également rendu au milieu d'autres types de graphiques dans la page.

  Chart.pluginService.register({
    beforeDraw: function(chart) {
      if (chart.canvas.id === 'doghnutChart') {
        let width = chart.chart.width,
            height = chart.chart.outerRadius * 2,
            ctx = chart.chart.ctx;

        rewardImg.width = 40;
        rewardImg.height = 40;
        let imageX = Math.round((width - rewardImg.width) / 2),
            imageY = (height - rewardImg.height ) / 2;

        ctx.drawImage(rewardImg, imageX, imageY, 40, 40);
        ctx.save();
      }
    }
  });

Puisqu'une légende (voir: http://www.chartjs.org/docs/latest/configuration/legend.html ) agrandit la hauteur du graphique, la valeur de la hauteur doit être obtenue par le rayon.

Larmia
la source
0

Tout d'abord, félicitations pour avoir choisi Chart.js! Je l'utilise sur l'un de mes projets actuels et je l'adore absolument - il fait parfaitement le travail.

Bien que les étiquettes / info-bulles ne fassent pas encore partie de la bibliothèque, vous voudrez peut-être jeter un coup d'œil à ces trois pull requests:

Et, comme Cracker0dks l'a mentionné, Chart.js utilise canvaspour le rendu afin que vous puissiez également implémenter vos propres info-bulles en interagissant directement avec lui.

J'espère que cela t'aides.

volpav
la source
0

La solution d'Alesana fonctionne très bien pour moi en général, mais comme d'autres, je voulais pouvoir spécifier où se produisent les sauts de ligne. J'ai fait quelques modifications simples pour envelopper les lignes aux caractères '\ n', tant que le texte est déjà enveloppé. Une solution plus complète forcerait le retour à la ligne s'il y a des caractères '\ n' dans le texte, mais je n'ai pas le temps pour le moment de faire fonctionner cela avec le dimensionnement des polices. Le changement se centre également un peu mieux horizontalement lors de l'enrubannage (évite les espaces de fuite). Le code est ci-dessous (je ne peux pas encore publier de commentaires).

Ce serait cool si quelqu'un mettait ce plug-in sur GitHub ...

Chart.pluginService.register({
  beforeDraw: function(chart) {
    if (chart.config.options.elements.center) {
      // Get ctx from string
      var ctx = chart.chart.ctx;

      // Get options from the center object in options
      var centerConfig = chart.config.options.elements.center;
      var fontStyle = centerConfig.fontStyle || 'Arial';
      var txt = centerConfig.text;
      var color = centerConfig.color || '#000';
      var maxFontSize = centerConfig.maxFontSize || 75;
      var sidePadding = centerConfig.sidePadding || 20;
      var sidePaddingCalculated = (sidePadding / 100) * (chart.innerRadius * 2)
      // Start with a base font of 30px
      ctx.font = "30px " + fontStyle;

      // Get the width of the string and also the width of the element minus 10 to give it 5px side padding
      var stringWidth = ctx.measureText(txt).width;
      var elementWidth = (chart.innerRadius * 2) - sidePaddingCalculated;

      // Find out how much the font can grow in width.
      var widthRatio = elementWidth / stringWidth;
      var newFontSize = Math.floor(30 * widthRatio);
      var elementHeight = (chart.innerRadius * 2);

      // Pick a new font size so it will not be larger than the height of label.
      var fontSizeToUse = Math.min(newFontSize, elementHeight, maxFontSize);
      var minFontSize = centerConfig.minFontSize;
      var lineHeight = centerConfig.lineHeight || 25;
      var wrapText = false;

      if (minFontSize === undefined) {
        minFontSize = 20;
      }

      if (minFontSize && fontSizeToUse < minFontSize) {
        fontSizeToUse = minFontSize;
        wrapText = true;
      }

      // Set font settings to draw it correctly.
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      var centerX = ((chart.chartArea.left + chart.chartArea.right) / 2);
      var centerY = ((chart.chartArea.top + chart.chartArea.bottom) / 2);
      ctx.font = fontSizeToUse + "px " + fontStyle;
      ctx.fillStyle = color;

      if (!wrapText) {
        ctx.fillText(txt, centerX, centerY);
        return;
      }

      var lines = [];
      var chunks = txt.split('\n');
      for (var m = 0; m < chunks.length; m++) {
        var words = chunks[m].split(' ');
        var line;

        // Break words up into multiple lines if necessary
        for (var n = 0; n < words.length; n++) {
          var testLine = (n == 0) ? words[n] : line + ' ' + words[n];
          var metrics = ctx.measureText(testLine);
          var testWidth = metrics.width;
          if (testWidth > elementWidth && n > 0) {
            lines.push(line);
            line = words[n];
          } else {
            line = testLine;
          }
        }
        lines.push(line);
      }

      // Move the center up depending on line height and number of lines
      centerY -= ((lines.length-1) / 2) * lineHeight;

      // All but last line
      for (var n = 0; n < lines.length; n++) {
        ctx.fillText(lines[n], centerX, centerY);
        centerY += lineHeight;
      }
    }
  }
});
sferrari
la source