[Chartjs]-Why is borderColor function in chartjs running multiple times, and how to reduce it?

0👍

I was able to figure it out, problem with default charts and chartjs docs, in general, is that it doesn’t mention that all the default options are run every time, and it doesn’t happen when you separately define the elements options in options, which we can define.

For example in a line chart, we can do options>elements>line>properties, this will only run after charts have been drawn so this significantly increases the efficiency and reduces processing, also you can reduce the function runs by half by disabling animation on the chart (options> animation: false)

So in my case, I was able to bring 25-time running function to 4 time running function by setting the above-mentioned things correctly.

Here is the updated js fiddle : https://jsfiddle.net/abhishek_soni/38mfez7g/57/

Also, here is the code snippet :

var ctx = document.getElementById('myChart').getContext('2d');

let i = 0,
  j = 0,
  k = 0;

var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
    datasets: [{
      label: '# of Votes',
      data: [12, 19, 3, 5, 2, 3],
      backgroundColor: [
        'rgba(255, 99, 132, 0.2)',
        'rgba(54, 162, 235, 0.2)',
        'rgba(255, 206, 86, 0.2)',
        'rgba(75, 192, 192, 0.2)',
        'rgba(153, 102, 255, 0.2)',
        'rgba(255, 159, 64, 0.2)'
      ],

    }]
  },
  options: {
    animation: false, // this reduces it by half as for all animations it's renders twice
    elements: { // this reduces it by number of options, as this is applied after the default options are run.
      line: {
        borderWidth: 1,
        borderColor: function() {
          ++i;
          console.log('why this bordercolor running this many times : ', i)
          return 'green'
        }
      },
    },
    responsive: function() {
      k++;
      console.log('why this option running this many times : ', k)
      return false
    },
    maintainAspectRatio: false,
    scales: {
      y: {
        beginAtZero: function() {
          j++;
          console.log('why this scale running this many times : ', j)
          return true
        }
      }
    }
  }
});
<canvas id="myChart" width="200" height="200"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.min.js" integrity="sha512-asxKqQghC1oBShyhiBwA+YgotaSYKxGP1rcSYTDrB0U6DxwlJjU59B67U8+5/++uFjcuVM8Hh5cokLjZlhm3Vg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2"></script>

0👍

As I read in the documentation of ChartJs, borderColor should be Color and also it’s Scribtable property, it means you can pass a function with context and options as parameters to have flexible ui

So it should be called each time context and options changed.

You can calculate your color value and pass it instead of passing function.

0👍

The bordercolor function is called everytime your chart needs to draw a border. If you assumed it would be called once, you can just create your own function and give bordercolor the return value of that function, not the function itself.

I don’t know, why it’s not recognizing variable gradient in jsfiddle

If you are trying to create a gradient, why would the amount of times this function is called matter in any way? I don’t think you understand what you are asking.

Here is your example with a gradient, assuming that is what you actually need: JSFiddle

var ctx = document.getElementById('myChart').getContext('2d');

let width, height, gradient;
function getGradient(ctx, chartArea) {
  const chartWidth = chartArea.right - chartArea.left;
  const chartHeight = chartArea.bottom - chartArea.top;
  if (gradient === null || width !== chartWidth || height !== chartHeight) {
    // Create the gradient because this is either the first render
    // or the size of the chart has changed
    width = chartWidth;
    height = chartHeight;
    gradient = ctx.createLinearGradient(0, chartArea.bottom, 0, chartArea.top);
    gradient.addColorStop(0, "rgb(54, 162, 235)");
    gradient.addColorStop(0.5, "rgb(255, 205, 86)");
    gradient.addColorStop(1, "rgb(255, 99, 132)");
  }

  return gradient;
}

var myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
    datasets: [{
      label: '# of Votes',
      data: [12, 19, 3, 5, 2, 3],
      backgroundColor: [
        'rgba(255, 99, 132, 0.2)',
        'rgba(54, 162, 235, 0.2)',
        'rgba(255, 206, 86, 0.2)',
        'rgba(75, 192, 192, 0.2)',
        'rgba(153, 102, 255, 0.2)',
        'rgba(255, 159, 64, 0.2)'
      ],
      borderColor: function(context) {
        const chart = context.chart;
        const {ctx, chartArea} = chart;

        if (!chartArea) {
          // This case happens on initial chart load
          return null;
        }
        return getGradient(ctx, chartArea);
      },
      borderWidth: 1
     }]
  },
  options: {
    responsive: false,
    maintainAspectRatio: false,
    scales: {
      y: {
        beginAtZero: true,
      }
    },
  }
});

Taken from here.

Leave a comment