I am using Doughnut chart from ng2-charts (http://valor-software.com/ng2-charts/) in angular 2. I have been searching for an option to put a text in the middle without success.
You can place both LABEL and its Value in center of Doughnut.
When you hover it hover value will be updated in the center of chart.
import { Component, OnInit } from '@angular/core';
import { ChartType } from 'chart.js';
import { SingleDataSet, Label, PluginServiceGlobalRegistrationAndOptions } from 'ng2-charts';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// Doughnut
public doughnutChartLabels = ['Download Sales', 'In-Store Sales'];
public doughnutChartData: SingleDataSet = [
[350, 450]
];
public doughnutChartType: ChartType = 'doughnut';
public doughnutChartPlugins: PluginServiceGlobalRegistrationAndOptions[] = [{
afterDraw(chart) {
const ctx = chart.ctx;
var txt1 = '';
var txt2 = '';
try{
var check = chart.active ? chart.tooltip._active[0]._datasetIndex : "None";
if(check !== "None"){
txt1 = chart.tooltip._data.labels[chart.tooltip._active[0]._index];
txt2 = chart.tooltip._data.datasets[0].data[chart.tooltip._active[0]._index];
}else{
txt1 = chart.tooltip._data.labels[0];
txt2 = chart.tooltip._data.datasets[0].data[0];
}
}
catch(err){
txt1 = chart.tooltip._data.labels[0]
txt2 = chart.tooltip._data.datasets[0].data[0];
}
//Get options from the center object in options
const sidePadding = 60;
const sidePaddingCalculated = (sidePadding / 100) * (chart.innerRadius * 2)
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const centerX = ((chart.chartArea.left + chart.chartArea.right) / 2);
const centerY = ((chart.chartArea.top + chart.chartArea.bottom) / 2);
//Get the width of the string and also the width of the element minus 10 to give it 5px side padding
const stringWidth = ctx.measureText(txt1).width;
const elementWidth = (chart.innerRadius * 2) - sidePaddingCalculated;
// Find out how much the font can grow in width.
const widthRatio = elementWidth / stringWidth;
const newFontSize = Math.floor(30 * widthRatio);
const elementHeight = (chart.innerRadius * 2);
// Pick a new font size so it will not be larger than the height of label.
const fontSizeToUse = 30;
ctx.font = fontSizeToUse + 'px Arial';
ctx.fillStyle = 'black';
// Draw text in center
ctx.fillText(txt2, centerX, centerY - 10);
var fontSizeToUse1 = 15;
ctx.font = fontSizeToUse1 + 'px Arial';
ctx.fillText(txt1, centerX, centerY + 10);
}
}];
constructor() { }
ngOnInit() {
}
// events
public chartClicked({ event, active }: { event: MouseEvent, active: {}[] }): void {
//console.log(event, active);
}
public chartHovered({ event, active }: { event: MouseEvent, active: {}[] }): void {
//console.log(event, active);
}
}
HTML
<div>
<div>
<div style="display: block">
<canvas baseChart [data]="doughnutChartData" [labels]="doughnutChartLabels" [chartType]="doughnutChartType"
[plugins]="doughnutChartPlugins" (chartHover)="chartHovered($event)"
(chartClick)="chartClicked($event)"></canvas>
</div>
</div>
</div>
Happy Coding :)
You can do the following to place text in the center of doughnut chart. It worked for me
HTML:
<div style="display: block">
<canvas #mycanvas baseChart
[data]="doughnutChartData"
[labels]="doughnutChartLabels"
[chartType]="doughnutChartType"
(chartHover)="chartHovered($event)"
(chartClick)="chartClicked($event)"></canvas>
</div>
Typescript
import {Component, NgModule, ElementRef, Inject, ViewChild} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {ChartsModule, Color} from 'ng2-charts';
export class App{
@ViewChild('mycanvas')
canvas:ElementRef;
ngOnInit(){
var ctx = this.canvas.nativeElement.getContext("2d");
let me = this;
this.options = {
circumference: Math.PI,
rotation : Math.PI,
animation:{ onComplete: function() {
me.doit(ctx);
}}
}
}
doit(ctx) {
// Chart.types.Doughnut.prototype.draw.apply(this, arguments);
var width = this.canvas.nativeElement.clientWidth,
height = this.canvas.nativeElement.clientHeight;
var fontSize = (height / 250).toFixed(2);
ctx.font = fontSize + "em Verdana";
ctx.textBaseline = "middle";
ctx.fillStyle = "blue";
var text = "Pass Rate 82%",
textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height -10;
ctx.fillText(text, textX, textY);
ctx.restore();
}
}
}