DEV Community

Ekta Prasad
Ekta Prasad

Posted on

3 2

Displaying customized labels for each coordinates in node.js using chart.js.

Graph demo / output of below code

The above image is the output of the code for this article.If you are desiring the same, you can continue reading this page.

To display customize data labels for each coordinate in node.js using chart.js is a bit different or difficult. I did it by importing another third-party library that was definitely hard to implement initially, I had to read the documentation and went through many StackOverflow answers to find the solutions. So here I am documenting all of it together.

Note: I assume you already have installed and use chart.js and chartjs-node-canvas, if not you can check out this link

Installing packages

First install chartjs-plugin-datalabels

npm i chartjs-plugin-datalabels;
Enter fullscreen mode Exit fullscreen mode

Now require it into your file :

const ChartDataLabels = require('chartjs-plugin-datalabels');
Enter fullscreen mode Exit fullscreen mode

Then you need to write

const chartJsFactory = () => {
    const Chart = require('chart.js');
    require('chartjs-plugin-datalabels');
    delete require.cache[require.resolve('chart.js')];
    delete require.cache[require.resolve('chartjs-plugin-datalabels')];
    return Chart;
    }
Enter fullscreen mode Exit fullscreen mode

Next, you need to customize the callback

const chartCallback = (ChartJS) => {
    ChartJS.plugins.register({
        ChartDataLabels
    });
};
Enter fullscreen mode Exit fullscreen mode

Now for using this, you need to pass it on service like this:

const canvasRenderService = new CanvasRenderService(width, height, chartCallback, undefined,chartJsFactory);
Enter fullscreen mode Exit fullscreen mode

Customizing Plugin

You customize the plugin inside the nested object like this

configuration = {
  options:{
      plugin:{

      }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now you can customize the plugin as the way you want.I have written few customizable elements, you can checkout the documentation for more here

plugins: {
    datalabels: {
        align: function(context) {
            return -45;
          },

        color: function(context) {
            return context.dataset.borderColor;
          },

        font: {
            size: 20,
            weight: 500
          },


        display: 'auto',  //hides overlapping data labels

        formatter: function(value, context) {
            if(value.indexLabel == '100%') {
                return 'Peak'
            }
            return value.indexLabel ;
        },
    }
  }
Enter fullscreen mode Exit fullscreen mode

Final code

Thank you for reading it till here. I hope it helps you.Below is the final code.

const { CanvasRenderService } = require('chartjs-node-canvas');
const ChartDataLabels = require('chartjs-plugin-datalabels');
const fs = require("fs");

const chartJsFactory = () => {
    const Chart = require('chart.js');
    require('chartjs-plugin-datalabels');
    delete require.cache[require.resolve('chart.js')];
    delete require.cache[require.resolve('chartjs-plugin-datalabels')];
    return Chart;
    }

const width = 1600;
const height = 750;
const chartCallback = (ChartJS) => {

    ChartJS.defaults.global.elements.point.pointStyle = "star";
    ChartJS.defaults.global.elements.point.radius = "4",
    ChartJS.defaults.global.elements.point.defaultFontSize = "90px",
    ChartJS.plugins.register({
        ChartDataLabels
    });


};
const canvasRenderService = new CanvasRenderService(width, height, chartCallback, undefined,chartJsFactory);


const createImage = async () => {
    let dataset1=[],dataset2=[],dataset3=[];

        dataset1 = [{x:123,y:45,indexLabel:'25%'},{x:115,y:65,indexLabel:'55%'},{x:128,y:195,indexLabel:'75%'},{x:723,y:145,indexLabel:'100%'}];
        dataset2 = [{x:239,y:27,indexLabel:'25%'},{x:498,y:25,indexLabel:'55%'},{x:318,y:95,indexLabel:'75%'},{x:933,y:195,indexLabel:'100%'}]


    const configuration = {
        type: 'line',
          data: {
              labels: [0,150,300,450,600,750,900,1050],
              datasets: [{
                  label: 'legend1',
                  data: dataset1,
                  fill: false,
                  borderColor: 'blue',
                  borderWidth: 3,
                  showLine: true,
                  xAxisID: 'xAxis1'
              },
              {
                  label: 'legend2',
                  data: dataset2,
                  fill: false,
                  borderColor: 'red',
                  borderWidth: 3,
                  xAxisID: 'xAxis1'
              }
              ],

          },
          options: {
            legend: {
                labels: {
                    filter: function(item, chart) {
                        return !item.text.includes('legend2'); // hides a particular legend
                    },
                    fontSize: 18
                }
            },
                  scales: {
                  xAxes:[
                      {
                    type:'linear'
                      id:'xAxis1',
                        ticks: {
                            beginAtZero: false,
                            max: 1000,
                            stepSize:50,
                            fontSize: 18,

                        },
                        scaleLabel: {
                            display: true,
                            labelString: 'x axis label',
                            fontSize: 20,
                            fontColor:'black'
                          },

                     },
                    ],
                    yAxes: [{
                    display: true,
                    ticks: {
                        max: 300,
                        stepSize: 20,
                        fontSize: 18
                    },
                    scaleLabel: {
                        display: true,
                        labelString: 'y axis label',
                        fontSize: 20,
                        fontColor:'black'
                    }
                }],
              },

            plugins: {
                datalabels: {
                    align: function(context) {
                        return -45;
                      },

                    color: function(context) {
                        return context.dataset.borderColor;
                      },

                    font: {
                        size: 20,
                        weight: 500
                      },


                    display: 'auto',  //hides overlapping data labels

                    formatter: function(value, context) {
                        if(value.indexLabel == '100%') {
                            return 'Peak'
                        }
                        return value.indexLabel ;
                    },
                }
              }
          }
          }

    const dataUrl = await canvasRenderService.renderToDataURL(configuration);
    return dataUrl;
};

module.exports = {
createImage
}
Enter fullscreen mode Exit fullscreen mode

Adios Amigo.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more →

Top comments (1)

Collapse
 
parimal20 profile image

Can you help me for my issue?
I want to begin from zero on the y-axis but after zero directly want to show dataset value on the y-axis as per I have attached image.
dev-to-uploads.s3.amazonaws.com/up...

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up