Chart.js: Dynamic background color (callback)

Created on 15 May 2016  路  6Comments  路  Source: chartjs/Chart.js

Hi there,

I got a case, where I need to dynamically set colors of single bars depending on the data value.

I would suggest to use a callback like this:

datasets: [{
  label: '# of Votes',
  data: [ 10, 21, 22 ],
  backgroundColor: function( value ) { // Callback instead of static color 
    if ( value < 30 ) {
      return 'red'; 
    }
    return 'green';
  }
}]
support

Most helpful comment

Turns out that, after diving more into it, using the plugin system is way more elegant.

For anybody who comes across the same problem, this does the job:

    Chart.pluginService.register({
        beforeUpdate: function( chartInstance ) {
            chartInstance.data.datasets.forEach( function( dataset ) {
                dataset.backgroundColor = dataset.data.map( function( data ) {
                    if ( typeof dataset.backgroundColor === "function" ) {
                        return dataset.backgroundColor.call( this, data );
                    }
                    return dataset.backgroundColor;
                });
            });
        }
    });

All 6 comments

@haschu I'm not sure this is the best way to do it. Given the way each chart is written, this would require a lot of duplicated code.

A better way to do this would be to use the plugin system introduced in v2.1.0. See my fiddle below for a quick implementation of this. Ideally the plugin would read from the config to get the thresholds and change the values accordingly

https://jsfiddle.net/kw6t06xb/1/

@etimberg Thanks for your response! I didn't know about the plugin system - really great tool!
Maybe your solution is something for more advanced users.

I solved this using the callback implementation (as I described above) like this:

In core.helper.js:

  // Old code
  helpers.callCallback = function(fn, args, _tArg) {
    if (fn && typeof fn.call === 'function') {
      fn.apply(_tArg, args);
    }
  };

  // New code
  helpers.isFunction = function(fn) {
    if (fn && typeof fn.call === 'function') {
      return true;
    }
    return false;
  };
  helpers.callCallback = function(fn, args, _tArg) {
    if (helpers.isFunction(fn)) {
      return fn.apply(_tArg, args);
    }
  };
  helpers.callIfCallback = function(fn, args, _tArg) {
    if (helpers.isFunction(fn)) {
      return helpers.callCallback(fn, args, _tArg);
    } else {
      return fn;
    }
  };

And then in the elements file (in this case element.rectangle.js):

// Old code
ctx.fillStyle = vm.backgroundColor;
ctx.strokeStyle = vm.borderColor;

// New code
var dataValue = this._chart.config.data.datasets[ this._datasetIndex ].data[ this._index ];
// ...
ctx.fillStyle = helpers.callIfCallback( vm.backgroundColor, [dataValue], this );
ctx.strokeStyle = helpers.callIfCallback( vm.borderColor, [dataValue], this );

Thats it.
IMHO it isn't that munch duplicate code.

For instance C3.js is doing it the same way, and it feels very familiar to me.
This functions could also be required in many use cases - but maybe I'm wrong.

Anyways - I could come up with a pull request, if you want.

Btw.: Chart.js 2 is by far the best JS chart library I've seen yet. Amazing work! :)

Turns out that, after diving more into it, using the plugin system is way more elegant.

For anybody who comes across the same problem, this does the job:

    Chart.pluginService.register({
        beforeUpdate: function( chartInstance ) {
            chartInstance.data.datasets.forEach( function( dataset ) {
                dataset.backgroundColor = dataset.data.map( function( data ) {
                    if ( typeof dataset.backgroundColor === "function" ) {
                        return dataset.backgroundColor.call( this, data );
                    }
                    return dataset.backgroundColor;
                });
            });
        }
    });

@haschu do you have a complete exemple where I can see how you integrate the plugin in your chart ?

Many thanks!!
I have research some days but get no way to do this...
thanks a lots.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nanospeck picture nanospeck  路  3Comments

HeinPauwelyn picture HeinPauwelyn  路  3Comments

lizbanach picture lizbanach  路  3Comments

akashrajkn picture akashrajkn  路  3Comments

Woogles picture Woogles  路  3Comments