web-dev-qa-db-fra.com

Comment afficher les valeurs de données de camembert de chaque tranche dans chart.js

J'utilise Chart.js pour dessiner un graphique en secteurs dans ma page php.J'ai trouvé info-bulle montrant chaque valeur de la tranche.
enter image description here

Mais je souhaite afficher ces valeurs comme ci-dessous image. enter image description here

Je ne sais pas comment faire cela avec chart.js.

Aidez-moi, s'il vous plaît.

Mon code Javascript:

function drawPie(canvasId,data,legend){
    var ctx = $("#pie-canvas-" + canvasId).get(0).getContext("2d");

    var piedata = [];
    $.each(data,function(i,val){
        piedata.Push({value:val.count,color:val.color,label:val.status});
    });
    var options =
    {
        tooltipTemplate: "<%= Math.round(circumference / 6.283 * 100) %>%",
    }
    var pie = new Chart(ctx).Pie(piedata,options);
    if(legend)document.getElementById("legend").innerHTML = pie.generateLegend();
}

code php:

printf('<table><tr>');
echo '<td style="text-align: right;"><canvas id="pie-canvas-'
    . $canvasId
    . '" width="256" height="256" ></canvas></td><td style="text-align: left;width:360px;height:auto" id="legend" class="chart-legend"></td></tr></table>';

     echo '<script type="text/javascript">drawPie('
    . $canvasId
    . ', '
    . $data3
    .', '
    . $legend
    . ');</script>';

enter image description here

20
Nithya.K

D'après ce que je sais, je ne pense pas que Chart.JS dispose d'une fonctionnalité permettant de dessiner du texte sur un graphique à secteurs. Mais cela ne signifie pas que vous ne pouvez pas le faire vous-même en JavaScript natif. Je vais vous donner un exemple sur la façon de procéder. Le code permettant de dessiner du texte pour chaque segment du graphique à secteurs est présenté ci-dessous:

function drawSegmentValues()
{
    for(var i=0; i<myPieChart.segments.length; i++) 
    {
        // Default properties for text (size is scaled)
        ctx.fillStyle="white";
        var textSize = canvas.width/10;
        ctx.font= textSize+"px Verdana";

        // Get needed variables
        var value = myPieChart.segments[i].value;
        var startAngle = myPieChart.segments[i].startAngle;
        var endAngle = myPieChart.segments[i].endAngle;
        var middleAngle = startAngle + ((endAngle - startAngle)/2);

        // Compute text location
        var posX = (radius/2) * Math.cos(middleAngle) + midX;
        var posY = (radius/2) * Math.sin(middleAngle) + midY;

        // Text offside to middle of text
        var w_offset = ctx.measureText(value).width/2;
        var h_offset = textSize/4;

        ctx.fillText(value, posX - w_offset, posY + h_offset);
    }
}

Un graphique à secteurs comporte un tableau de segments stockés dans PieChart.segments. Nous pouvons examiner les startAngle et endAngle de ces segments pour déterminer l'angle entre le texte middleAngle. Ensuite, nous avancerions dans cette direction de Radius/2 Pour être au centre de la carte en radians.

Dans l'exemple ci-dessus, d'autres opérations de nettoyage sont effectuées. En raison de la position du texte dessiné dans fillText() étant le coin supérieur droit, nous devons obtenir des valeurs de décalage pour corriger cela. Et finalement textSize est déterminé en fonction de la taille du graphique lui-même, plus le graphique est grand, plus le texte est volumineux.

Exemple de violon


Avec de légères modifications, vous pouvez modifier les valeurs de nombres discrets d'un jeu de données en nombres de centiles dans un graphique. Pour ce faire, obtenez le total value des éléments de votre jeu de données, appelez ceci totalValue. Ensuite, sur chaque segment, vous pouvez trouver le pourcentage en faisant:

Math.round(myPieChart.segments[i].value/totalValue*100)+'%';

La section ici myPieChart.segments[i].value/totalValue Est ce qui calcule le pourcentage que prend le segment dans le graphique. Par exemple, si le segment en cours avait une valeur de 50 Et que la valeur totale était de 200. Ensuite, le pourcentage pris par le segment serait: 50/200 => 0.25. Le reste est de faire ce look Nice. 0.25*100 => 25, Nous ajoutons un % À la fin. Pour les nombres entiers de pourcentages, j'ai arrondi à l'entier le plus proche, mais cela peut entraîner des problèmes de précision. Si nous avons besoin de plus de précision, vous pouvez utiliser .toFixed(n) pour enregistrer les décimales. Par exemple, nous pourrions le faire pour enregistrer une décimale unique au besoin:

var value = myPieChart.segments[i].value/totalValue*100;
if(Math.round(value) !== value)
    value = (myPieChart.segments[i].value/totalValue*100).toFixed(1);
value = value + '%';

Exemple de violon de centiles avec des nombres décimaux

Fiddle Exemple de percentile avec des entiers

16
Spencer Wieczorek

Pour Chart.js 2.0 et les versions ultérieures, les données de l'objet Graphique ont été modifiées. Pour ceux qui utilisent Chart.js 2.0+, voici un exemple d'utilisation de la méthode HTML5 Canvas fillText() pour afficher la valeur des données à l'intérieur de la tranche de camembert. Le code fonctionne également pour le graphique en anneau, la seule différence étant que type: 'pie' contre type: 'doughnut' lors de la création du graphique.

Script:

Javascript

var data = {
    datasets: [{
        data: [
            11,
            16,
            7,
            3,
            14
        ],
        backgroundColor: [
            "#FF6384",
            "#4BC0C0",
            "#FFCE56",
            "#E7E9ED",
            "#36A2EB"
        ],
        label: 'My dataset' // for legend
    }],
    labels: [
        "Red",
        "Green",
        "Yellow",
        "Grey",
        "Blue"
    ]
};

var pieOptions = {
  events: false,
  animation: {
    duration: 500,
    easing: "easeOutQuart",
    onComplete: function () {
      var ctx = this.chart.ctx;
      ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
      ctx.textAlign = 'center';
      ctx.textBaseline = 'bottom';

      this.data.datasets.forEach(function (dataset) {

        for (var i = 0; i < dataset.data.length; i++) {
          var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
              total = dataset._meta[Object.keys(dataset._meta)[0]].total,
              mid_radius = model.innerRadius + (model.outerRadius - model.innerRadius)/2,
              start_angle = model.startAngle,
              end_angle = model.endAngle,
              mid_angle = start_angle + (end_angle - start_angle)/2;

          var x = mid_radius * Math.cos(mid_angle);
          var y = mid_radius * Math.sin(mid_angle);

          ctx.fillStyle = '#fff';
          if (i == 3){ // Darker text color for lighter background
            ctx.fillStyle = '#444';
          }
          var percent = String(Math.round(dataset.data[i]/total*100)) + "%";      
          //Don't Display If Legend is hide or value is 0
          if(dataset.data[i] != 0 && dataset._meta[0].data[i].hidden != true) {
            ctx.fillText(dataset.data[i], model.x + x, model.y + y);
            // Display percent in another line, line break doesn't work for fillText
            ctx.fillText(percent, model.x + x, model.y + y + 15);
          }
        }
      });               
    }
  }
};

var pieChartCanvas = $("#pieChart");
var pieChart = new Chart(pieChartCanvas, {
  type: 'pie', // or doughnut
  data: data,
  options: pieOptions
});

HTML

<canvas id="pieChart" width=200 height=200></canvas>

jsFiddle

53
Hung Tran

J'ai trouvé un excellent Chart.js plugin qui fait exactement ce que vous voulez: https://github.com/emn178/Chart.PieceLabel.js

21
Kamil Bednarz

Vous pouvez utiliser le plugin PieceLabel pour Chart.js.

{pieceLabel: {mode: 'pourcentage', précision: 2}}

démo | Documentation

Le plugin semble avoir un nouvel emplacement (et nom): DémoDocs .

11
JKR

La réponse de @Hung Tran fonctionne parfaitement. En guise d’amélioration, je suggérerais de ne pas afficher les valeurs égales à 0. Supposons que vous avez 5 éléments et que 2 d’entre eux sont 0 et que le reste d’entre eux ont des valeurs, la solution ci-dessus indique 0 et 0%. Il vaut mieux filtrer cela avec une vérification différente de 0!

          var val = dataset.data[i];
          var percent = String(Math.round(val/total*100)) + "%";

          if(val != 0) {
            ctx.fillText(dataset.data[i], model.x + x, model.y + y);
            // Display percent in another line, line break doesn't work for fillText
            ctx.fillText(percent, model.x + x, model.y + y + 15);
          }

Code mis à jour ci-dessous:

var data = {
    datasets: [{
        data: [
            11,
            16,
            7,
            3,
            14
        ],
        backgroundColor: [
            "#FF6384",
            "#4BC0C0",
            "#FFCE56",
            "#E7E9ED",
            "#36A2EB"
        ],
        label: 'My dataset' // for legend
    }],
    labels: [
        "Red",
        "Green",
        "Yellow",
        "Grey",
        "Blue"
    ]
};

var pieOptions = {
  events: false,
  animation: {
    duration: 500,
    easing: "easeOutQuart",
    onComplete: function () {
      var ctx = this.chart.ctx;
      ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
      ctx.textAlign = 'center';
      ctx.textBaseline = 'bottom';

      this.data.datasets.forEach(function (dataset) {

        for (var i = 0; i < dataset.data.length; i++) {
          var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
              total = dataset._meta[Object.keys(dataset._meta)[0]].total,
              mid_radius = model.innerRadius + (model.outerRadius - model.innerRadius)/2,
              start_angle = model.startAngle,
              end_angle = model.endAngle,
              mid_angle = start_angle + (end_angle - start_angle)/2;

          var x = mid_radius * Math.cos(mid_angle);
          var y = mid_radius * Math.sin(mid_angle);

          ctx.fillStyle = '#fff';
          if (i == 3){ // Darker text color for lighter background
            ctx.fillStyle = '#444';
          }

          var val = dataset.data[i];
          var percent = String(Math.round(val/total*100)) + "%";

          if(val != 0) {
            ctx.fillText(dataset.data[i], model.x + x, model.y + y);
            // Display percent in another line, line break doesn't work for fillText
            ctx.fillText(percent, model.x + x, model.y + y + 15);
          }
        }
      });               
    }
  }
};

var pieChartCanvas = $("#pieChart");
var pieChart = new Chart(pieChartCanvas, {
  type: 'pie', // or doughnut
  data: data,
  options: pieOptions
});
1
Srihari Sridharan