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

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

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

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

e depois na function drawPieSegments

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

Veja esta atração: https://github.com/nnnick/Chart.js/pull/35

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

Nenhuma das outras respostas redimensionou o texto com base na quantidade de texto e no tamanho do donut. Aqui está um pequeno script que você pode usar para colocar dinamicamente qualquer quantidade de texto no meio e redimensioná-lo automaticamente. http://jsfiddle.net/nkzyx50o/

Donut com texto dinâmico no meio

Vai levar qualquer quantidade de texto no donut tamanho perfeito para o donut. Para evitar tocar nas bordas, você pode definir um acolchoamento lateral como uma porcentagem do diâmetro interno 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 plug-in começará com um tamanho de fonte básico de 30px. De lá, ele irá verificar a largura do texto e compará-lo com o raio do círculo e redimensioná-lo com base na relação entre o círculo e a largura do texto.

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 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); //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; //Draw text in center ctx.fillText(txt, centerX, centerY); } } }); 

E você usa as seguintes opções no seu object gráfico

 options: { elements: { center: { text: 'Desktop', color: '#36A2EB', //Default black fontStyle: 'Helvetica', //Default Arial sidePadding: 15 //Default 20 (as a percentage) } } } 

Aqui está limpo e combinado exemplo de soluções acima – responsivo (tente resize a janela), suporta auto-alinhamento 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 }); 
        

Eu evitaria modificar o código chart.js para conseguir isso, já que é bem fácil com CSS e HTML comuns. Aqui está minha solução:

HTML:

  
47 / 60 st
(30 / 25 st)

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 é assim:

insira a descrição da imagem aqui

Isso também está funcionando no meu fim …

 
99%
Total

insira a descrição da imagem aqui

Base em @ resposta rap-2-h, Aqui o código para usar o texto no gráfico de rosca no Chart.js para usar no painel como. Tem tamanho de fonte dynamic para a opção responsiva.

HTML:

 
text

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 code.try para resize a janela. http://jsbin.com/wapono/13/edit

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

Eu tive um problema com o alinhamento do texto no Google Chrome quando a legenda é exibida, pois a altura do gráfico não inclui isso, portanto, ela não está alinhada corretamente no meio. Corrigido isso pela contabilidade para isso no cálculo de fontSize e textY.

Eu calculei porcentagem dentro do método, em vez de um valor definido, pois tenho vários deles na página. Supõe-se que o gráfico só tem 2 valores (caso contrário, qual é a porcentagem de? E que o primeiro é o que você deseja mostrar a porcentagem. Eu tenho um monte de outros charts também, então eu faço uma verificação para type = donut. Eu estou usando apenas donuts para mostrar 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, então me deparei com um problema ao resize que o texto mudaria de cor (entre preto e a principal em um caso e secundário e branco em outro) Eu “salve” qualquer que seja o estilo de preenchimento existente, desenhe o texto (na cor dos dados primários) e depois restaure o estilo de preenchimento antigo. (Preservar o estilo de preenchimento antigo não parece necessário, mas você nunca 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(); } } }); 
 var data = { labels: ["Red","Blue"], datasets: [ { data: [300, 50], backgroundColor: ["#FF6384","#36A2EB"], }] }; 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(); } } }); var myChart = new Chart(document.getElementById('myChart'), { type: 'doughnut', data: data, options: { responsive: true, legend: { display: true } } }); 
   

Você também pode colar o código do onAnimationComplete na opção onAnimationComplete :

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

O texto será mostrado depois da animação

Eu crio uma demonstração com 7 jQueryUI Slider e ChartJs (com texto dynamic 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 NO JSFIDDLE

insira a descrição da imagem aqui

@ rap-2-h e @Ztuons A resposta de Ch não permite que a opção showTooltips esteja ativa, mas o que você pode fazer é criar e colocar em camadas um segundo object de canvas atrás do que renderiza o gráfico.

A parte importante é o estilo exigido nos divs e para o próprio object de canvas, de forma que eles sejam renderizados uns sobre os outros.

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

Você pode usar o css com posicionamento relativo / absoluto, se desejar que ele seja responsivo. Além disso, ele pode lidar facilmente com a linha múltipla.

https://jsfiddle.net/mgyp0jkk/

 

Some text

Some text

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

Um pequeno aprimoramento: faz sentido verificar o ID de canvas apropriado, consulte o snippet modificado abaixo. Caso contrário, o texto (ou seja, 75%) também será renderizado no meio de outros tipos de charts 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 (consulte: http://www.chartjs.org/docs/latest/configuration/legend.html ) amplia a altura do gráfico, o valor da altura deve ser obtido pelo raio.

Primeiro de tudo, kudos sobre a escolha Chart.js! Eu estou usando em um dos meus projetos atuais e eu absolutamente amo isso – faz o trabalho perfeitamente.

Embora os labels / dicas ainda não façam parte da biblioteca, convém dar uma olhada nestes três pedidos de solicitação:

  • Dicas de ferramentas
  • Adicionamos labels aos charts de pizza
  • Adicionado labels básicos ao gráfico de pizza

E, como Cracker0dks mencionou, o Chart.js usa a canvas para renderizar, assim você também pode implementar suas próprias dicas interagindo diretamente com ele.

Espero que isto ajude.