Website-Suche

javascript - Wie fügt man Text innerhalb des Donut-Diagramms mit Chart.js hinzu?


Wie man Text innerhalb des Doughnut-Diagramms darstellt, ich verwende ChartJs.

Antwort #1

Keine der anderen Antworten passt den Text basierend auf der Textmenge und der Größe des Donuts an. Hier ist ein kleines Skript, das Sie verwenden können, um eine beliebige Textmenge in der Mitte zu platzieren, und es wird automatisch die Größe anpassen.

Beispiel: http://jsfiddle.net/kdvuxbtj/

Es wird jede Textmenge aufnehmen, die in die Donut-große Form passt, perfekt für den Donut. Um zu vermeiden, dass die Ränder berührt werden, können Sie ein Seitenabstand als Prozentsatz des Durchmessers des Inneren des Kreises festlegen. Wenn Sie es nicht festlegen, beträgt der Standardwert 20. Sie können auch die Farbe, die Schriftart und den Text auswählen. Das Plugin kümmert sich um den Rest.

Der Plugin-Code beginnt mit einer Basis-Schriftgröße von 30px. Von dort aus wird die Breite des Textes überprüft und mit dem Radius des Kreises verglichen und basierend auf dem Verhältnis von Kreis- zu Textbreite angepasst.

Es hat eine standardmäßige minimale Schriftgröße von 20px. Wenn der Text bei der minimalen Schriftgröße die Grenzen überschreiten würde, wird der Text umbrochen. Die standardmäßige Zeilenhöhe beim Umbrechen des Textes beträgt 25px, aber Sie können sie ändern. Wenn Sie die standardmäßige minimale Schriftgröße auf false setzen, wird der Text unendlich klein und wird nicht umgebrochen.

Es hat auch eine standardmäßige maximale Schriftgröße von 75px, falls nicht genug Text vorhanden ist und die Buchstaben zu groß wären.

Dies ist der Plugin-Code

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

Und Sie verwenden die folgenden Optionen in Ihrem Diagrammobjekt

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

Gutschrift an @Jenna Sloan für die Hilfe bei den in dieser Lösung verwendeten mathematischen Berechnungen.

Antwort #2

Hier ist ein bereinigtes und kombiniertes Beispiel der obigen Lösungen - responsiv (versuche, die Fenstergröße zu ändern), unterstützt selbstanpassende Animationen, unterstützt Tooltips

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>

AKTUALISIERUNG 17.06.16:

Gleiche Funktionalität, aber für chart.js Version 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>

Antwort #3

Ich würde vermeiden, den Chart.js-Code zu ändern, um dies zu erreichen, da es mit normalem CSS und HTML ziemlich einfach ist. Hier ist meine Lösung:

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

Die Ausgabe sieht so aus:

Antwort #4

Sie müssen den Code folgendermaßen ändern: in chart.Doughnut.defaults

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

und dann in der Funktion drawPieSegments

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

Sieh dir diesen Pull an: https://github.com/nnnick/Chart.js/pull/35

Hier ist ein Fiddle http://jsfiddle.net/mayankcpdixit/6xV78/, das dasselbe implementiert.

Antwort #5

Das funktioniert auch bei mir...

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

Antwort #6

Du kannst CSS mit relativer/absoluter Positionierung verwenden, wenn du es responsiv haben möchtest. Außerdem kann es problemlos mehrzeiligen Text handhaben.

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>

Antwort #7

Basierend auf der Antwort von @rap-2-h, hier ist der Code zur Verwendung von Text auf einem Doughnut-Diagramm in Chart.js zur Verwendung in einem Dashboard. Es hat eine dynamische Schriftgröße für responsive Optionen.

HTML :

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

Skript :

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

Hier ist der Beispielcode. Versuche, das Fenster zu vergrößern oder zu verkleinern. http://jsbin.com/wapono/13/edit

Verwandte Artikel