Comment rendre le texte à l'intérieur du graphique en anneau, j'utilise ChartJs .
Vous devez modifier le code comme suit: in chart.Doughnut.defaults
labelFontFamily : "Arial",
labelFontStyle : "normal",
labelFontSize : 24,
labelFontColor : "#666"
puis en fonction drawPieSegments
ctx.fillText(data[0].value + "%", width/2 - 20, width/2, 200);
Voir ce pull: https://github.com/nnnick/Chart.js/pull/35
voici un violon http://jsfiddle.net/mayankcpdixit/6xV78/ implémentant la même chose.
Aucune des autres réponses ne redimensionne le texte en fonction de la quantité de texte et de la taille du beignet. Voici un petit script que vous pouvez utiliser pour placer dynamiquement toute quantité de texte au milieu et le redimensionner automatiquement. http://jsfiddle.net/nkzyx50o/
Il faudra n'importe quelle quantité de texte dans le beignet, taille idéale pour le beignet. Pour éviter de toucher les bords, vous pouvez définir un remplissage latéral en tant que pourcentage du diamètre à l'intérieur du cercle. Si vous ne le définissez pas, la valeur par défaut sera 20. Vous aurez également la couleur, la police et le texte. Le plugin s'occupe du reste.
Le code du plugin commencera par une taille de police de base de 30px. À partir de là, il vérifie la largeur du texte, le compare au rayon du cercle et le redimensionne en fonction du rapport largeur/cercle.
C'est le code du 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);
}
}
});
Et vous utilisez les options suivantes dans votre objet graphique
options: {
elements: {
center: {
text: 'Desktop',
color: '#36A2EB', //Default black
fontStyle: 'Helvetica', //Default Arial
sidePadding: 15 //Default 20 (as a percentage)
}
}
}
Nous remercions @ Jenna Sloan pour l’aide apportée aux calculs utilisés dans cette solution.
Voici nettoyé et combiné l'exemple des solutions ci-dessus - responsive (essayez de redimensionner la fenêtre), prend en charge l'animation s'alignant automatiquement, prend en charge les info-bulles
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:
Même fonctionnalité mais pour 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>
Pour ce faire, j'éviterais de modifier le code chart.js, car c'est assez facile avec CSS et HTML classiques. Voici ma solution:
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;
}
La sortie ressemble à ceci:
Cela fonctionne aussi à ma fin ...
<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" />
Base sur la réponse @ rap-2-h, voici le code pour utiliser du texte sur un graphique en anneau sur Chart.js pour l’utiliser dans un tableau de bord, comme. Il a une taille de police dynamique pour l’option responsive.
HTML:
<div>text
<canvas id="chart-area" width="300" height="300" style="border:1px solid"/><div>
Scénario:
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);
}
});
});
Voici l'exemple de code.try pour redimensionner la fenêtre. http://jsbin.com/wapono/13/edit
Ceci est basé sur la mise à jour de Cmyker pour Chart.js 2. (posté comme une autre réponse car je ne peux pas commenter pour le moment)
J'ai eu un problème d'alignement du texte sur Chrome lorsque la légende est affichée, car la hauteur du graphique n'inclut pas cette valeur, de sorte qu'elle n'est pas alignée correctement au milieu. Ce problème a été corrigé en tenant compte de cela dans le calcul de fontSize et textY.
J'ai calculé le pourcentage à l'intérieur de la méthode plutôt qu'une valeur définie, car j'en ai plusieurs sur la page. On suppose que votre graphique n'a que 2 valeurs (sinon, quel est le pourcentage de? Et que la première est celle pour laquelle vous voulez afficher le pourcentage. J'ai aussi d'autres graphiques, alors je vérifie le type = donut. J'utilise uniquement des beignets pour afficher les pourcentages, donc cela fonctionne pour moi.
La couleur du texte semble un peu aléatoire en fonction de l'ordre dans lequel les choses se passent, etc. Je "sauvegarde" quel que soit le style de remplissage existant, dessine le texte (dans la couleur des données primaires) puis restaure l'ancien style de remplissage. (Préserver l'ancien style de remplissage ne semble pas nécessaire, mais on ne sait jamais.)
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
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.bundle.js"></script>
<canvas id="myChart"></canvas>
Vous pouvez également coller le code de mayankcpdixit dans l'option onAnimationComplete
:
// ...
var myDoughnutChart = new Chart(ctx).Doughnut(data, {
onAnimationComplete: function() {
ctx.fillText(data[0].value + "%", 100 - 20, 100, 200);
}
});
Le texte sera affiché après l'animation
Je crée une démo avec 7 jQueryUI Slider et ChartJs (avec du texte dynamique à l'intérieur)
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
});
Vous pouvez utiliser css avec positionnement relatif/absolu si vous le souhaitez réactif. De plus, il peut gérer facilement les lignes multiples.
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>
La réponse de @ rap-2-h et @Ztuons Ch ne permet pas à l'option showTooltips
d'être active, mais vous pouvez créer et superposer un second objet canvas
derrière celui qui représente le graphique. .
La partie importante est le style requis dans les divs et pour l’objet de travail lui-même, afin qu’ils s’affichant les uns sur les autres.
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>
Voici le jsfiddle: https://jsfiddle.net/68vxqyak/1/
@Cmyker, excellente solution pour chart.js v2
Une petite amélioration: il est judicieux de vérifier l'ID de canevas approprié, voir l'extrait modifié ci-dessous. Sinon, le texte (75%) est également affiché au milieu des autres types de graphique de la page.
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();
}
}
});
Comme une légende (voir: http://www.chartjs.org/docs/latest/configuration/legend.html ) grossit la hauteur du graphique, la valeur de height devrait être obtenue par le rayon.
Tout d’abord, félicitations pour le choix de Chart.js! Je l’utilise sur l’un de mes projets en cours et j’adore ça, c’est un travail parfait.
Bien que les étiquettes/info-bulles ne fassent pas encore partie de la bibliothèque, vous pouvez jeter un œil à ces trois demandes d'extraction:
Et, comme Cracker0dks est mentionné, Chart.js utilise canvas
pour le rendu afin que vous puissiez tout aussi bien implémenter vos propres info-bulles en interagissant directement avec celle-ci.
J'espère que cela t'aides.