Antworten:
Sie müssen den Code wie folgt ändern: in chart.Doughnut.defaults
labelFontFamily : "Arial",
labelFontStyle : "normal",
labelFontSize : 24,
labelFontColor : "#666"
und dann in Funktion drawPieSegments
ctx.fillText(data[0].value + "%", width/2 - 20, width/2, 200);
Siehe diesen Pull: https://github.com/nnnick/Chart.js/pull/35
Hier ist eine Geige http://jsfiddle.net/mayankcpdixit/6xV78/ , die dasselbe implementiert.
Keine der anderen Antworten ändert die Größe des Textes basierend auf der Textmenge und der Größe des Donuts. Hier ist ein kleines Skript, mit dem Sie eine beliebige Textmenge dynamisch in der Mitte platzieren können. Die Größe wird automatisch geändert.
Beispiel: http://jsfiddle.net/kdvuxbtj/
Es wird jede Menge Text in dem Donut benötigt, der perfekt für den Donut geeignet ist. Um ein Berühren der Kanten zu vermeiden, können Sie eine Seitenpolsterung als Prozentsatz des Durchmessers der Innenseite des Kreises festlegen. Wenn Sie es nicht einstellen, wird es standardmäßig auf 20 gesetzt. Sie auch die Farbe, die Schriftart und den Text. Das Plugin kümmert sich um den Rest.
Der Plugin-Code beginnt mit einer Basisschriftgröße von 30px. Von dort aus wird die Breite des Texts überprüft, mit dem Radius des Kreises verglichen und die Größe basierend auf dem Verhältnis von Kreis zu Textbreite geändert.
Die Standardschriftgröße beträgt mindestens 20 Pixel. Wenn der Text bei der Mindestschriftgröße die Grenzen überschreitet, wird der Text umbrochen. Die Standardzeilenhöhe beim Umbrechen des Texts beträgt 25 Pixel, Sie können sie jedoch ändern. Wenn Sie die Standard-Mindestschriftgröße auf false setzen, wird der Text unendlich klein und wird nicht umgebrochen.
Es hat auch eine maximale Standardschriftgröße von 75px, falls nicht genügend Text vorhanden ist und die Beschriftung zu groß wäre.
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
}
}
}
Dank an @Jenna Sloan für die Hilfe bei der in dieser Lösung verwendeten Mathematik.
Hier finden Sie ein bereinigtes und kombiniertes Beispiel für die oben genannten Lösungen - reaktionsschnell (versuchen Sie, die Größe des Fensters zu ändern), unterstützt die Selbstausrichtung der Animation und unterstützt QuickInfos
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>
UPDATE 17.06.16:
Gleiche Funktionalität, jedoch 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>
Uncaught TypeError: Cannot read property 'extend' of undefined
irgendwelche Ideen?
Ich würde es vermeiden, den Code von chart.js zu ändern, um dies zu erreichen, da dies 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 folgendermaßen aus:
Das funktioniert auch an meinem Ende ...
<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>
Basis auf @ rap-2-h Antwort, hier der Code für die Verwendung von Text auf Donut-Diagramm auf Chart.js für die Verwendung in Dashboard wie. Es hat eine dynamische Schriftgröße für die Reaktionsoption.
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 der Beispielcode. Versuchen Sie, die Größe des Fensters zu ändern. http://jsbin.com/wapono/13/edit
Sie können CSS mit relativer / absoluter Positionierung verwenden, wenn Sie möchten, dass es reagiert. Außerdem kann es problemlos mit mehreren Leitungen umgehen.
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>
Dies basiert auf Cmykers Update für Chart.js 2. (als weitere Antwort veröffentlicht, da ich noch keinen Kommentar abgeben kann)
Ich hatte ein Problem mit der Textausrichtung in Chrome, wenn die Legende angezeigt wird, da die Diagrammhöhe dies nicht enthält und sie daher in der Mitte nicht richtig ausgerichtet ist. Dies wurde behoben, indem dies bei der Berechnung von fontSize und textY berücksichtigt wurde.
Ich habe den Prozentsatz innerhalb der Methode berechnet und nicht einen festgelegten Wert, da ich mehrere davon auf der Seite habe. Es wird davon ausgegangen, dass Ihr Diagramm nur 2 Werte hat (andernfalls wie viel Prozent davon? Und dass der erste derjenige ist, für den Sie den Prozentsatz anzeigen möchten. Ich habe auch eine Reihe anderer Diagramme, also überprüfe ich, ob type = donut. Ich verwende nur Donuts, um Prozentsätze anzuzeigen, damit es für mich funktioniert.
Die Textfarbe scheint ein bisschen ein Hit und Miss zu sein, abhängig von der Reihenfolge, in der die Dinge ausgeführt werden usw. Daher stieß ich beim Ändern der Größe auf ein Problem, dass der Text seine Farbe ändern würde (in einem Fall zwischen Schwarz und Primärfarbe und in einem anderen Fall zwischen Sekundärfarbe und Weiß) Ich "speichere" unabhängig vom vorhandenen Füllstil, zeichne den Text (in der Farbe der Primärdaten) und stelle dann den alten Füllstil wieder her. (Die Beibehaltung des alten Füllstils scheint nicht erforderlich zu sein, aber Sie wissen es nie.)
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();
}
}
});
Sie können auch den Code von mayankcpdixit in die folgende onAnimationComplete
Option einfügen :
// ...
var myDoughnutChart = new Chart(ctx).Doughnut(data, {
onAnimationComplete: function() {
ctx.fillText(data[0].value + "%", 100 - 20, 100, 200);
}
});
Der Text wird nach der Animation angezeigt
save
Methode
Ich erstelle eine Demo mit 7 jQueryUI Slider und ChartJs (mit dynamischem Text)
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
});
Die Antwort von @ rap-2-h und @Ztuons Ch lässt nicht zu, dass die showTooltips
Option aktiv ist, aber Sie können eine Sekunde erstellen und überlagerncanvas
Objekt hinter dem Objekt .
Der wichtige Teil ist das Styling, das in den Divs und für das Canvas-Objekt selbst erforderlich ist, damit sie übereinander gerendert werden.
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>
Hier ist die jsfiddle: https://jsfiddle.net/68vxqyak/1/
@Cmyker, großartige Lösung für chart.js v2
Eine kleine Verbesserung: Es ist sinnvoll, nach der entsprechenden Canvas-ID zu suchen (siehe das modifizierte Snippet unten). Andernfalls wird der Text (dh 75%) auch in der Mitte anderer Diagrammtypen auf der Seite gerendert.
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();
}
}
});
Da eine Legende (siehe: http://www.chartjs.org/docs/latest/configuration/legend.html ) die Diagrammhöhe vergrößert, sollte der Wert für die Höhe durch den Radius ermittelt werden.
Zunächst einmal ein großes Lob für die Wahl von Chart.js! Ich benutze es für eines meiner aktuellen Projekte und ich liebe es absolut - es macht den Job perfekt.
Obwohl Beschriftungen / QuickInfos noch nicht Teil der Bibliothek sind, sollten Sie sich diese drei Pull-Anforderungen ansehen:
Und wie Cracker0dks erwähnt, verwendet Chart.jscanvas
zum Rendern verwendet, sodass Sie auch einfach Ihre eigenen Tooltips implementieren können, indem Sie direkt damit interagieren.
Hoffe das hilft.
Die Lösung von Alesana funktioniert im Allgemeinen sehr gut für mich, aber wie andere wollte ich angeben können, wo Zeilenumbrüche auftreten. Ich habe einige einfache Änderungen vorgenommen, um Zeilen mit '\ n' Zeichen zu umbrechen, solange der Text bereits umbrochen wird. Eine vollständigere Lösung würde das Umbrechen erzwingen, wenn der Text '\ n' Zeichen enthält, aber ich habe im Moment keine Zeit, dies mit der Schriftgröße zu tun. Die Änderung zentriert sich beim Wickeln auch horizontal etwas besser (vermeidet Leerzeichen). Der Code ist unten (ich kann noch keine Kommentare posten).
Es wäre cool, wenn jemand dieses Plug-In auf GitHub stellen würde ...
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;
}
}
}
});