Search code examples
chart.jsstyling

Center point labels between ticks (Polar Area Chart JS)


I'm using Chart JS in which I have a polar area chart (see image https://i.sstatic.net/f1CQs.jpg) I want the point labels to be centered between the ticks. I have found solutions that only seem to work with bar charts that have an X and Y axis by using.

xAxes: [{
            gridLines: {
                offsetGridLines: true
            }
        ]} 

But this does not seem to work when using a polar area chart.

My code is

import React, { Component } from "react";
import Chart from "chart.js";

export default class OrdersFufilledChart extends Component {
  OrdersFufilledChart = React.createRef();

  componentDidMount() {
    const OrdersFufilledChart = this.OrdersFufilledChart.current.getContext(
      "2d"
    );

    new Chart(OrdersFufilledChart, {
      type: "polarArea",
        data: {
            datasets: [
                {
                    data: [342, 323, 333, 352, 361, 299, 272, 423, 425, 400, 382, 363],
                    backgroundColor: ["#57C5C8", "#57C5C8", "#57C5C8", "#57C5C8", "#57C5C8", "#ff0931", "#ff0931","#57C5C8","#57C5C8","#57C5C8","#57C5C8","#57C5C8"],
                    borderWidth: 4,
                    hoverBorderColor: "white",
                }
            ],
        labels: [
          "JAN",
          "FEB",
          "MAR",
          "APR",
          "MAY",
          "JUN",
          "JUL",
          "AUG",
          "SEP",
          "OCT",
          "NOV",
          "DEC"
        ],

      },
        options: {

            responsive: true,
            plugins: {
                datalabels: {
                    display: false,
                },

            },
            cutoutPercentage: 20,
            legend: {
                display: false
            },
            layout: {
                padding: 0,

            },
            scale: {
                scaleLabel: {
                    display: true
                },

           ticks: {
            max: 450,
            maxTicksLimit: 1,
                    display: false,

          },
          angleLines: {
            display: true
          },
            pointLabels: {
                display: true
            }
          },

      }
    });
  }
  render() {
    return (
      <div>
        <canvas
          id="OrdersFufilledChart"
          ref={this.OrdersFufilledChart}
          width={360}
          height={360}
        />
      </div>
    );
  }
}

Any insight on how I can do this or pointers in the right direction will be greatly appreciated.

EDIT

I'm looking for something like this with the labels between inbetween. https://imgur.com/gallery/L7P7qmu


Solution

  • What about using the datalabels-plugin for that?

    I guess you saw my other answer where I used this plugin because your code has many similarities to mine.

    I improved my code so it's responsive now. The labels are even animated. I don't share OP's concerns of the other question (offtopic: can somebody correct this genitive here? I know it's wrong...) with cluttered labels in this case because of the small 3-char-labels.

    Complete code: https://jsbin.com/hamekugoja/2/edit?js,output

    let myChart = new Chart(document.getElementById("pie-chart"), {
      type: "polarArea",
      data: {
        datasets: [{
          data: [342, 323, 333, 352, 361, 299, 272, 423, 425, 400, 382, 363],
          backgroundColor: ["#57C5C8", "#57C5C8", "#57C5C8", "#57C5C8", "#57C5C8", "#ff0931", "#ff0931", "#57C5C8", "#57C5C8", "#57C5C8", "#57C5C8", "#57C5C8"],
          borderWidth: 4,
          hoverBorderColor: "white",
        }],
        labels: [
          "JAN",
          "FEB",
          "MAR",
          "APR",
          "MAY",
          "JUN",
          "JUL",
          "AUG",
          "SEP",
          "OCT",
          "NOV",
          "DEC"
        ],
      },
      options: {
        responsive: true,
        plugins: {
          datalabels: {
            formatter: function(value, context) {
              return context.chart.data.labels[context.dataIndex];
            },
            anchor: 'start',
            align: 'end',
            offset: 0 // Gets updated
          },
        },
        cutoutPercentage: 20,
        legend: {
          display: false
        },
        layout: {
          padding: 30,
        },
        scale: {
          scaleLabel: {
            display: true
          },
          ticks: {
            max: 450,
            maxTicksLimit: 1,
            display: false,
          },
          angleLines: {
            display: true
          },
          pointLabels: {
            display: false
          }
        },
        onResize: function() {
          let width = document.getElementById("pie-chart").width
          let padding = myChart.options.layout.padding
          myChart.options.plugins.datalabels.offset = width/2-padding
        }
      }
    });
    
    function updateOffset() {
      let width = document.getElementById("pie-chart").width
      let padding = myChart.options.layout.padding
      myChart.options.plugins.datalabels.offset = width/2-padding
      myChart.update()
    }
    updateOffset() //init call after we know the dimensions of the chart