Chart.js - donut tag positioning

I have a webpage using Chart.js. On this page, I draw three donut charts. In the middle of each chart, I want to show the percentage of the filled donut. I currently have the following code that can be seen in this Fiddle .

function setupChart(chartId, progress) { var canvas = document.getElementById(chartId); var context = canvas.getContext('2d'); var remaining = 100 - progress; var data = { labels: [ 'Progress', '', ], datasets: [{ data: [progress, remaining], backgroundColor: [ '#8FF400', '#FFFFFF' ], borderColor: [ '#8FF400', '#408A00' ], hoverBackgroundColor: [ '#8FF400', '#FFFFFF' ] }] }; var options = { responsive: true, maintainAspectRatio: false, scaleShowVerticalLines: false, cutoutPercentage: 80, legend: { display: false }, animation: { onComplete: function () { var xCenter = (canvas.width / 2) - 20; var yCenter = canvas.height / 2 - 40; context.textAlign = 'center'; context.textBaseline = 'middle'; var progressLabel = data.datasets[0].data[0] + '%'; context.font = '20px Helvetica'; context.fillStyle = 'black'; context.fillText(progressLabel, xCenter, yCenter); } } }; Chart.defaults.global.tooltips.enabled = false; var chart = new Chart(context, { type: 'doughnut', data: data, options: options }); } 

The graph is working. But the problem is rendering the label. The label is not vertically and horizontally centered in the middle of the donut. The position of the cue also changes based on the screen resolution. You can see the position of the label change by changing the size of the frame that is displayed in the diagrams in Fiddle .

My question is, how can I sequentially position the percentage in the middle of the donut? My page is a responsive page, therefore it is important to have consistent positioning. But I'm not sure what else to do. I feel that the textAlign and textBaseline not working, or I do not understand their use.

Thanks!

+6
source share
6 answers

According to this answer, you can do this with a plugin in a different version. I don’t know if you noticed, but if you increase the width and decrease it again and again on your violin, the height of your canvas becomes more and more (the diagram goes further and further down).

In the version you are using, you can expand the doughnut controller as follows:

http://jsfiddle.net/ivanchaer/cutkqkuz/1/

 Chart.defaults.DoughnutTextInside = Chart.helpers.clone(Chart.defaults.doughnut); Chart.controllers.DoughnutTextInside = Chart.controllers.doughnut.extend({ draw: function(ease) { var ctx = this.chart.chart.ctx; var data = this.getDataset(); var easingDecimal = ease || 1; Chart.helpers.each(this.getDataset().metaData, function(arc, index) { arc.transition(easingDecimal).draw(); var vm = arc._view; var radius = (vm.outerRadius + vm.innerRadius) / 2; var thickness = (vm.outerRadius - vm.innerRadius) / 2; var angle = Math.PI - vm.endAngle - Math.PI / 2; ctx.save(); ctx.fillStyle = vm.backgroundColor; ctx.font = "20px Verdana"; ctx.textAlign = 'center'; ctx.textBaseline = "middle"; var text = data.data[0] + '%'; ctx.fillStyle = '#000'; ctx.fillText(text, $(ctx.canvas).width()/2, $(ctx.canvas).height()/2); }); ctx.fillStyle = '#fff'; ctx.fill(); ctx.restore(); } }); function setupChart(chartId, progress) { var canvas = document.getElementById(chartId); var context = canvas.getContext('2d'); var remaining = 100 - progress; var deliveredData = { labels: [ "Value" ], datasets: [{ data: [progress, remaining], backgroundColor: [ '#8FF400', '#FFFFFF' ], borderColor: [ '#8FF400', '#408A00' ], hoverBackgroundColor: [ '#8FF400', '#FFFFFF' ] }] }; var deliveredOpt = { cutoutPercentage: 88, animation: false, legend: { display: false }, tooltips: { enabled: false } }; var chart = new Chart(canvas, { type: 'DoughnutTextInside', data: deliveredData, options: deliveredOpt }); } setupChart('standChart', 33); setupChart('moveChart', 66); setupChart('exerciseChart', 99); 
+4
source

See http://jsfiddle.net/uha5tseb/2/

It can be processed to obtain the width / height of each chart at this link

  onComplete: function (event) { console.log(this.chart.height); var xCenter = this.chart.width/2; var yCenter = this.chart.height/2; context.textAlign = 'center'; context.textBaseline = 'middle'; var progressLabel = data.datasets[0].data[0] + '%'; context.font = '20px Helvetica'; context.fillStyle = 'black'; context.fillText(progressLabel, xCenter, yCenter); } 

Hope this solves your problem!

+2
source

You set your variables incorrectly when you get xCenter and yCenter. Currently they do not get the middle of the canvas.

You have:

 var xCenter = (canvas.width / 2) - 20; var yCenter = canvas.height / 2 - 40; 

It should be:

 var xCenter = (canvas.width / 2); var yCenter = (canvas.height / 2); 
+2
source

I am not familiar with chart.js, but as I understood from the documentation, they provide a generateLegend method for your purposes. It returns data from legendCallback that you can display on a page outside the canvas.

The legend text container can be aligned with the canvas cover.

HTML:

 <div class="chart" data-legend=""> <canvas id="standChart"></canvas> </div> 

JS:

 var container = canvas.parentElement; ... container.setAttribute('data-legend', chart.generateLegend()); 

Fiddle

0
source

One way to resolve this issue is to add an absolutely positioned element on top of the canvas.

You can add a div element after each canvas element and then set its style:

 .precentage { font-family: tahoma; font-size: 28px; left: 50%; position: absolute; top: 50%; transform: translate(-50%, -50%); } 

Here is the full JSFiddle .

0
source
 We Give Size of the Chart Can be with in the Chart And Align to center on the Give the hight width based on the Chart Hight and Width.. i will make simple change in Your Jsfiddle .. xcenter and y center with the half distence for chart.. [http://jsfiddle.net/uha5tseb/10/][1] 
-one
source

Source: https://habr.com/ru/post/1012759/


All Articles