Home > front end >  Vue Chart 3 - Doughnut Charts with Text in the Middle (Trouble registering a plugin)
Vue Chart 3 - Doughnut Charts with Text in the Middle (Trouble registering a plugin)

Time:01-08

EDIT: My codesandbox is working, but it's not perfect. In my actual project I've better utilized ts and am just making an if check for the charttype so the font doesn't paste on all the charts you have. I still need to work on making the fontsize responsive and prettier, but I will try and update the codesandbox as much as I can!

If anyone would like to add to it please do! Also, post your link in the comments so anyone else having these issues can see them too!

I am attempting to make a doughnut chart that looks like this:

enter image description here

I've been trying to figure out how to get the code in this example using VueChartJS (VueChart3 is a TS safe rewrite of VueChartJS and works the same, just in composition API), but cannot figure out how to get the plugins to work properly.

vue-chartjs - Doughnut chart with text in the middle

Working Example from post

The example in the post above uses a textCenter() function and constantly access the context ctx variable. The first error I get however reads Property 'pluginService' does not exist on type 'typeof Chart' and also a Cannot read properties of undefined (reading 'register'). I think this has to do with the way VueChart3 and it's Chart.register(...registerables) line.

I've commented out all of the code that breaks the chart currently while I try and fix this issue. I am really stumped on where to go with this now and could really use a bit guidance.

Cheers!

CodeSandbox Link

Chart2.vue

<template>
  <div style="display: flex; justify-content: center; margin: 5rem">
    <DoughnutChart :options="options" v-bind="doughnutChartProps" />
  </div>
</template>

<script lang='ts'>
import { computed, ref, onMounted } from "vue";
import { DoughnutChart, useDoughnutChart } from "vue-chart-3";
import { Chart, ChartData, ChartOptions, registerables } from "chart.js";
Chart.register(...registerables, plugin);
var plugin = function (chart) {
  var width = chart.chart.width;
  var height = chart.chart.height;
  var ctx = chart.chart.ctx;

  ctx.restore();
  var fontSize = (height / 114).toFixed(2);
  ctx.font = fontSize   "em sans-serif";
  ctx.textBaseline = "middle";

  var text = 800;
  var textX = Math.round((width - ctx.measureText(text).width) / 2);
  var textY = height / 2;

  ctx.fillText(text, textX, textY);
  ctx.save();
};

export default {
  name: "Home",
  components: { DoughnutChart },
  setup(props) {
    const isResponsive = ref(true);
    const getData = computed<ChartData<"doughnut">>(() => ({
      labels: ["Success"],
      datasets: [
        {
          data: [10, 90],
          backgroundColor: ["#56cd92", "#f0f7ff"],
        },
      ],
    }));
    onMounted(() => {
      addPlugin({
        id: "my-plugin",
        beforeDraw: plugin,
      });
      // renderChart(chartdata, options);
      // textCenter(1000);
    });
    const options = computed<ChartOptions<"doughnut">>(() => ({
      plugins: {
        legend: {
          position: "bottom",
        },
      },
    }));

    const { doughnutChartProps } = useDoughnutChart({
      options,
      chartData: getData,
    });
    return {
      isResponsive,
      getData,
      options,
      doughnutChartProps,
    };
  },
};
</script>

CodePudding user response:

This is because pluginService is V2 syntax, to register plugins globally in V3 you can do it the same way you did with the registerables like so:

Chart.register(plugin)

You can even do it in the same register call like so:

Chart.register(...registerables, plugin)

Edit:
Plugins also have to be objects so chart.js knows which hook to use as you did in the mounted so your plugin variable has to look like this (still V2 syntax, you will need to change this yourself) to work:

var plugin = {
 id: 'idOfPlugin', 
 beforeDraw: function (chart) {
  var width = chart.chart.width;
  var height = chart.chart.height;
  var ctx = chart.chart.ctx;

  ctx.restore();
  var fontSize = (height / 114).toFixed(2);
  ctx.font = fontSize   "em sans-serif";
  ctx.textBaseline = "middle";

  var text = 800;
  var textX = Math.round((width - ctx.measureText(text).width) / 2);
  var textY = height / 2;

  ctx.fillText(text, textX, textY);
  ctx.save();
 };
}
  •  Tags:  
  • Related