How to get Chart js with observable centered text in angular?

Viewed 670

I'm using ng2 charts and chart.js for making a doughnut chart.

I've a requirement for centering text inside a doughnut chart. I've used the following approach.

https://stackblitz.com/edit/ng2-charts-doughnut-centertext?file=src%2Fapp%2Fapp.component.html

However I'm not being able to update the centered text's value dynamically.

I've an input property called

@Input() total;

and I want this inside:

  public doughnutChartPlugins: PluginServiceGlobalRegistrationAndOptions[] = [{
    afterDraw(chart) {
      const ctx = chart.ctx;
      const txt = this.total;

      //Get options from the center object in options
      const sidePadding = 60;
      const sidePaddingCalculated = (sidePadding / 100) * (chart.options.circumference / Math.PI)

      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(txt).width;
      const elementWidth = (chart.options.circumference / Math.PI) - sidePaddingCalculated;

      // Find out how much the font can grow in width.
      const widthRatio = elementWidth / stringWidth;
      const newFontSize = Math.floor(30 * widthRatio);
      const elementHeight = (chart.options.circumference / Math.PI);

      // Pick a new font size so it will not be larger than the height of label.
      const fontSizeToUse = Math.min(newFontSize, elementHeight);

      ctx.font = 'Arial';
      ctx.fillStyle = 'white';

      // Draw text in center
      ctx.fillText(this.total, centerX, centerY);
    }
  }];

How can I achieve that?

Currently it is showing undefined since the afterDraw(chart) code runs before component initialization.

Or is there a way to work it out using css (since the observable are directly available inside template.html)

Someone please help.

1 Answers

I'm facing the same issue. I resolved it by defining the "doughnutChartPlugins" as a public variable. you can also see this in the given code.

public text= 4;
public doughnutChartPlugins: PluginServiceGlobalRegistrationAndOptions[]=[{}];

ngAfterViewInit() {
  let that=this;
  this.doughnutChartPlugins= [{
    beforeDraw(chart) {
      const ctx = chart.ctx;
      //write your code 
      ctx.fillText(that.text, centerX, centerY);
    }
  }]
}
Related