Como adicionar texto dentro do gráfico de rosca usando Chart.js?

100

Como renderizar texto dentro do gráfico de rosca, estou usando ChartJs .

shashisp
fonte

Respostas:

36

Você tem que modificar o código como: em chart.Doughnut.defaults

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

e então em função drawPieSegments

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

Veja este pull: https://github.com/nnnick/Chart.js/pull/35

aqui está um violino http://jsfiddle.net/mayankcpdixit/6xV78/ implementando o mesmo.

mayankcpdixit
fonte
2
Há mais alguém que não consegue encontrar esta função drawPieSegments?
Yulian
2
Vale a pena mencionar que não funciona com a v2. Use o código jsfiddle incluído para facilitar o uso
Alwin Kesler
1
Como adicionar o% em uma nova linha? isso é suportado?
user7334203
1
Ainda assim, esta é a solução?
ACB de
@ ArunC.B - role para baixo
ashleedawg
176

Nenhuma das outras respostas redimensiona o texto com base na quantidade de texto e no tamanho da rosca. Aqui está um pequeno script que você pode usar para colocar dinamicamente qualquer quantidade de texto no meio e ele será redimensionado automaticamente.

Exemplo: http://jsfiddle.net/kdvuxbtj/

Donut com texto dinâmico no meio

Aceita qualquer quantidade de texto no donut de tamanho perfeito para o donut. Para evitar tocar nas bordas, você pode definir um preenchimento lateral como uma porcentagem do diâmetro do interior do círculo. Se você não definir, o padrão será 20. Você também a cor, a fonte e o texto. O plugin cuida do resto.

O código do plugin começará com um tamanho de fonte básico de 30px. A partir daí, ele irá verificar a largura do texto e compará-lo com o raio do círculo e redimensioná-lo com base na proporção círculo / largura do texto.

Ele tem um tamanho de fonte mínimo padrão de 20 px. Se o texto exceder os limites do tamanho mínimo da fonte, ele quebrará o texto. A altura padrão da linha ao quebrar o texto é 25px, mas você pode alterá-la. Se você definir o tamanho mínimo da fonte padrão como falso, o texto se tornará infinitamente pequeno e não será quebrado.

Ele também tem um tamanho de fonte máximo padrão de 75 px, caso não haja texto suficiente e as letras sejam muito grandes.

Este é o código do 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);
    }
  }
});

E você usa as seguintes opções em seu objeto gráfico

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

Agradecemos a @Jenna Sloan pela ajuda com a matemática usada nesta solução.

Alesana
fonte
5
Funciona bem! A maioria das outras opções é interrompida quando a legenda está à direita ou à esquerda.
louisav
2
Solução incrível!
JustLooking 01 de
3
Eu atualizei seu violino e adicionei um tamanho máximo de fonte: jsfiddle.net/nkzyx50o/3059
Felix Geenen
4
É possível dividir o texto em várias linhas? Meu texto tem 6 palavras e seu transbordamento entre os limites do recorte
Quanda 05/08/19
2
Obrigado, isso funciona para mim também, mas como adiciono texto de várias linhas?
Ashutosh Shrestha
54

Aqui está um exemplo limpo e combinado das soluções acima - responsivo (tente redimensionar a janela), suporta autoalinhamento de animação, suporta dicas de ferramentas

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>

ATUALIZAÇÃO 17.06.16:

Mesma funcionalidade, mas para chart.js versão 2:

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
fonte
3
Estou tendo Uncaught TypeError: Cannot read property 'extend' of undefinedalguma ideia?
Max Rose-Collins
2
Além disso, você pode alterar a cor do texto usando ctx.fillStyle = 'black';
Adrian Lopez
isso continua escrevendo sobre o texto repetidas vezes se o gráfico for atualizado fornecendo novos parâmetros de dados
techie_28
Você já descobriu a solução para isso?
Cmyker
@Cmyker, a solução CSS / HTML pode ajudar, mas não exporta o texto central quando o gráfico é exportado como PNG. Alguma ideia para corrigir isso? Esta foi uma solução completa, mas não limpa a área central quando o gráfico é atualizado .
techie_28
38

Eu evitaria modificar o código chart.js para fazer isso, uma vez que é muito fácil com CSS e HTML regulares. Esta é minha solução:

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

A saída é semelhante a esta:

insira a descrição da imagem aqui

Mattias
fonte
4
Por que não? Basta adicionar @ media-queries às suas aulas.
Mattias de
2
Não funciona para mim, estou usando uma forma responsiva, então não posso usar valores fixos. :(
Massa
2
@Massa você já tentou usar consultas de mídia para as várias resoluções? Ou modificando o css que escrevi para usar% em vez de px?
Mattias
2
@Mattias esta foi uma boa solução, mas o texto central não é exportado quando o gráfico é baixado como PNG.
techie_28
1
@ techie_28 ponto válido, não levou isso em consideração, pois a questão não mencionava a exportação.
Mattias
20

Isso também está funcionando no meu fim ...

<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>

insira a descrição da imagem aqui

Amrik Singh
fonte
4
Usei sua solução porque foi a mais rápida e faz o seu trabalho. Obrigado!
MDT
@Amrik Singh esta é uma boa solução, mas o texto central não será exportado se o gráfico for baixado como uma imagem PNG.
techie_28 01 de
Boa solução, não precisa de muito aborrecimento.
Shashank
você é meu cara! Não consigo encontrar solução no angularjs e nunca pensei assim. Surpreendente.
Nomi Ali
1
solução adorável, rápida e limpa
Khaleel
11

Baseie-se na resposta @ rap-2-h, aqui está o código para usar o texto no gráfico de rosca no Chart.js para usar no painel como. Possui tamanho de fonte dinâmico para opção responsiva.

HTML:

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

Roteiro:

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

Aqui, o código de amostra. Tenta redimensionar a janela. http://jsbin.com/wapono/13/edit

Ztuons Ch
fonte
1
Esta deve ser a resposta aceita em caso de necessidade de agilidade (meu caso).
Greg Blass
2
Se você tiver dicas de ferramentas, o texto desaparece ao passar o mouse.
Yulian
Erro "exceção jQuery.Deferred: Gráfico não definido"
Kiquenet
11

Você pode usar css com posicionamento relativo / absoluto se quiser responsivo. Além disso, pode controlar facilmente as linhas múltiplas.

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
fonte
bela solução :)
Manza
Super trabalho mano você fez meu dia
DVP SmartCreators Inc fazemos
8

Isso é baseado na atualização do Cmyker para Chart.js 2. (postado como outra resposta, pois ainda não posso comentar)

Tive um problema com o alinhamento do texto no Chrome quando a legenda é exibida, pois a altura do gráfico não inclui isso, por isso não está alinhado corretamente no meio. Corrigido isso, contabilizando isso no cálculo de fontSize e textY.

Calculei a porcentagem dentro do método, em vez de um valor definido, pois tenho vários deles na página. As suposições são de que seu gráfico tem apenas 2 valores (caso contrário, qual é a porcentagem de? E que o primeiro é aquele para o qual você deseja mostrar a porcentagem. Eu também tenho vários outros gráficos, então faço uma verificação para type = donut. Só estou usando donuts para mostrar as porcentagens, então funciona para mim.

A cor do texto parece um pouco imprevisível dependendo da ordem em que as coisas são executadas, etc., então tive um problema ao redimensionar que o texto mudaria de cor (entre preto e a cor primária em um caso, e a cor secundária e branco em outro). Eu "salvo" qualquer que seja o estilo de preenchimento existente, desenho o texto (na cor dos dados primários) e restauro o estilo de preenchimento antigo. (Preservar o estilo de preenchimento antigo não parece necessário, mas nunca se sabe.)

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
fonte
7

Você também pode colar o código de mayankcpdixit na onAnimationCompleteopção:

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

O texto será mostrado após a animação

rap-2-h
fonte
6
Bom, mas o texto desaparece ao passar o mouse
rnaud
1
Correto, o texto desaparece ao passar o mouse ... :( Seria ótimo se o texto não desaparecesse, alguma ideia de como fazer isso? Obrigado
MDT
@MDT @maud pode estar usando o savemétodo
techie_28
7

Eu crio uma demonstração com 7 jQueryUI Slider e ChartJs (com texto dinâmico dentro)

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

DEMO EM JSFIDDLE

insira a descrição da imagem aqui

Stéphane GRILLON
fonte
3

A resposta de @ rap-2-he @Ztuons Ch não permite a showTooltipsopção de estar ativo, mas o que você pode fazer é criar e colocar em camadas um segundo canvasobjeto atrás daquele que renderiza o gráfico.

A parte importante é o estilo exigido nas divs e no próprio objeto de tela para que sejam renderizados um sobre o outro.

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>

Aqui está o jsfiddle: https://jsfiddle.net/68vxqyak/1/

RYUUSEiiSTAR
fonte
1

@Cmyker, ótima solução para chart.js v2

Um pequeno aprimoramento: faz sentido verificar o id do canvas apropriado, veja o snippet modificado abaixo. Caso contrário, o texto (ou seja, 75%) também é renderizado no meio de outros tipos de gráfico na página.

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

Como uma legenda (ver: http://www.chartjs.org/docs/latest/configuration/legend.html ) aumenta a altura do gráfico, o valor da altura deve ser obtido pelo raio.

Larmia
fonte
0

Em primeiro lugar, parabéns por escolher Chart.js! Estou usando em um dos meus projetos atuais e absolutamente adoro - ele faz o trabalho perfeitamente.

Embora rótulos / dicas de ferramentas ainda não façam parte da biblioteca, você pode dar uma olhada nestas três solicitações pull:

E, como o Cracker0dks mencionou, o Chart.js usa canvaspara renderização, então você também pode implementar suas próprias dicas de ferramentas interagindo com ele diretamente.

Espero que isto ajude.

Volpav
fonte
0

A solução do Alesana funciona muito bem para mim em geral, mas como outros, eu queria ser capaz de especificar onde ocorrem as quebras de linha. Fiz algumas modificações simples para quebrar as linhas em '\ n' caracteres, desde que o texto já esteja sendo quebrado. Uma solução mais completa forçaria o empacotamento se houver qualquer caractere '\ n' no texto, mas não tenho tempo no momento para fazer isso funcionar com o tamanho da fonte. A mudança também centra um pouco melhor horizontalmente ao embrulhar (evita espaços residuais). O código está abaixo (não posso postar comentários ainda).

Seria legal se alguém colocasse este plug-in no 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
fonte