Chart.js Doughnut With Rounded Edges And Text Centered


Answer :

With v2.1.3, you can use the pluginService to do this


Preview

enter image description here


Script

// round corners Chart.pluginService.register({     afterUpdate: function (chart) {         if (chart.config.options.elements.arc.roundedCornersFor !== undefined) {             var arc = chart.getDatasetMeta(0).data[chart.config.options.elements.arc.roundedCornersFor];             arc.round = {                 x: (chart.chartArea.left + chart.chartArea.right) / 2,                 y: (chart.chartArea.top + chart.chartArea.bottom) / 2,                 radius: (chart.outerRadius + chart.innerRadius) / 2,                 thickness: (chart.outerRadius - chart.innerRadius) / 2 - 1,                 backgroundColor: arc._model.backgroundColor             }         }     },      afterDraw: function (chart) {         if (chart.config.options.elements.arc.roundedCornersFor !== undefined) {             var ctx = chart.chart.ctx;             var arc = chart.getDatasetMeta(0).data[chart.config.options.elements.arc.roundedCornersFor];             var startAngle = Math.PI / 2 - arc._view.startAngle;             var endAngle = Math.PI / 2 - arc._view.endAngle;              ctx.save();             ctx.translate(arc.round.x, arc.round.y);             console.log(arc.round.startAngle)             ctx.fillStyle = arc.round.backgroundColor;             ctx.beginPath();             ctx.arc(arc.round.radius * Math.sin(startAngle), arc.round.radius * Math.cos(startAngle), arc.round.thickness, 0, 2 * Math.PI);             ctx.arc(arc.round.radius * Math.sin(endAngle), arc.round.radius * Math.cos(endAngle), arc.round.thickness, 0, 2 * Math.PI);             ctx.closePath();             ctx.fill();             ctx.restore();         }     }, });  // write text plugin Chart.pluginService.register({     afterUpdate: function (chart) {         if (chart.config.options.elements.center) {             var helpers = Chart.helpers;             var centerConfig = chart.config.options.elements.center;             var globalConfig = Chart.defaults.global;             var ctx = chart.chart.ctx;              var fontStyle = helpers.getValueOrDefault(centerConfig.fontStyle, globalConfig.defaultFontStyle);             var fontFamily = helpers.getValueOrDefault(centerConfig.fontFamily, globalConfig.defaultFontFamily);              if (centerConfig.fontSize)                 var fontSize = centerConfig.fontSize;                 // figure out the best font size, if one is not specified             else {                 ctx.save();                 var fontSize = helpers.getValueOrDefault(centerConfig.minFontSize, 1);                 var maxFontSize = helpers.getValueOrDefault(centerConfig.maxFontSize, 256);                 var maxText = helpers.getValueOrDefault(centerConfig.maxText, centerConfig.text);                  do {                     ctx.font = helpers.fontString(fontSize, fontStyle, fontFamily);                     var textWidth = ctx.measureText(maxText).width;                      // check if it fits, is within configured limits and that we are not simply toggling back and forth                     if (textWidth < chart.innerRadius * 2 && fontSize < maxFontSize)                         fontSize += 1;                     else {                         // reverse last step                         fontSize -= 1;                         break;                     }                 } while (true)                 ctx.restore();             }              // save properties             chart.center = {                 font: helpers.fontString(fontSize, fontStyle, fontFamily),                 fillStyle: helpers.getValueOrDefault(centerConfig.fontColor, globalConfig.defaultFontColor)             };         }     },     afterDraw: function (chart) {         if (chart.center) {             var centerConfig = chart.config.options.elements.center;             var ctx = chart.chart.ctx;              ctx.save();             ctx.font = chart.center.font;             ctx.fillStyle = chart.center.fillStyle;             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.fillText(centerConfig.text, centerX, centerY);             ctx.restore();         }     }, }) 

and then

    ...     options: {         elements: {             arc: {                 roundedCornersFor: 0             },             center: {                 // the longest text that could appear in the center                 maxText: '100%',                 text: '67%',                 fontColor: '#FF6684',                 fontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",                 fontStyle: 'normal',                 // fontSize: 12,                 // if a fontSize is NOT specified, we will scale (within the below limits) maxText to take up the maximum space in the center                 // if these are not specified either, we default to 1 and 256                 minFontSize: 1,                 maxFontSize: 256,             }         }     } }; 

You can get rid of a bit of code if you don't want it to be generic (eg. if you fix the fontSize, if you fix the index to round, etc.)


Fiddle - http://jsfiddle.net/cd3fdoy9/


I've added a piece of code to change the center text when legend is clicked.

afterDraw: function (chart) {     if (chart.center) {         var ctx = chart.chart.ctx;          var i,a,s;         var n = chart;         var total = 0;         for(i=0,a=(n.data.datasets||[]).length;a>i;++i){             s = n.getDatasetMeta(i);             var x;             for(x=0; x<s.data.length; x++){                 if (!s.data[x].hidden)                     total += n.data.datasets[i].data[x];             }         }          ctx.save();         ctx.font = chart.center.font;         ctx.fillStyle = chart.center.fillStyle;         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.fillText(total, centerX, centerY);         ctx.restore();     } } 

Fiddle - http://jsfiddle.net/cd3fdoy9/49/


Comments

Popular posts from this blog

Are Regular VACUUM ANALYZE Still Recommended Under 9.1?

Can Feynman Diagrams Be Used To Represent Any Perturbation Theory?