As dev manager for the chart components, I'm frequently asked about how to configure the charts for different use cases, and there's one question that seems to come up more often than any other. How can we take a simple bar chart like this one and show each bar in a different color?

barColors1.png

While it's something that our charts easily support, this question always makes me cringe. After all, varying the bar colors can decrease readability of the data set, while also increasing the chances of colors clashing with other components on the page. If used purely for aesthetic reasons, this can have exactly the opposite effect, but there are cases where varying the bar color can make a lot of sense:

  1. If there are multiple visualizations on the page, and color is used consistently across the visualizations.
  2. If the color is used to represent another data dimension.
  3. If the colors have some built in meaning that helps the user to understand the data. For example, if Celtics was green and Lakers were purple.

 

Because the varying colors can be used effectively in these cases, I'm going to show how to handle this for the JET charts. If you're new to JET, then I'd recommend looking at Two-Way Data Binding JET Components with Knockout or the JET Hands-On-Lab to get started.

 

JS Data:

var DATA = [
  {city: "Boston", team: "Celtics", conference: "East", count: 17},
  {city: "Los Angeles", team: "Lakers", conference: "West", count: 16},
  {city: "Chicago", team: "Bulls", conference: "East", count: 6},
  {city: "San Antonio", team: "Spurs", conference: "West", count: 5},
  {city: "Golden State", team: "Warriors", conference: "West", count: 4},
  {city: "Philadelphia", team: "76ers", conference: "East", count: 3},
  {city: "Detroit", team: "Pistons", conference: "East", count: 3},
  {city: "Miami", team: "Heat", conference: "East", count: 3},
  {city: "New York", team: "Knicks", conference: "East", count: 2},
  {city: "Houston", team: "Rockets", conference: "West", count: 2}
];






HTML: Just a simple chart whose series and groups will be populated by the Knockout view model.

<div id="chart" data-bind="ojComponent: {
  component: 'ojChart',
  series: chartSeries, groups: chartGroups,
  title: {text: 'Teams With Multiple NBA Championships', halign: 'center'}
}" style="width:600px;height:300px;">
</div>






JS: The chartSeries and chartGroups are constructed by looping over the data set. Since a chart is being used, it's important to list the 'ojs/ojchart' in the require call (not shown below).

function ViewModel() {
  var self = this;

  // ColorAttributeGroupHandler to assign colors.
  var colorHandler = new oj.ColorAttributeGroupHandler();

  // Create data for a chart with 1 series and multiple groups.
  self.chartGroups = [];
  self.chartSeries = [{name: 'Count', items: [], displayInLegend: 'off'}];
  for(var i=0; i<DATA.length; i++) {
    var item = DATA[i];
    self.chartGroups.push(item.team);
    self.chartSeries[0].items.push({
      value: item.count,
      color: colorHandler.getValue(item.team)
    });
  }
}





 

This code is the same as what would be used to render the original chart, with just two changes:

  • color (JS Line 5): We use the oj.ColorAttributeGroupHandler to assign colors from the default color ramp based on the input to its getValue function. The color is then passed via the color field of the series item.
  • displayInLegend (JS Line 9): Since the color of the bars no longer match the default series color, we set displayInLegend to off to prevent the series label from showing in the legend. No legend entries are needed since they would be redundant with the x-axis labels.

barColors2.png

As shown above, this bar chart doesn't meet any of the 3 qualifications for having different bar colors. It isn't being shown alongside other visualizations with the same coloring scheme, and the colors don't have any built in meaning. Let's change this chart so that the color is used to represent another data dimension:

 

HTML: We will add a new legend declaration in the data-bind. This will populate a custom legend section based on the value of legendItems from the view model.

legend: {
  sections: [{items: legendItems}],
  title: 'Conference'
}




 

JS: First we'll change the color to depend on the conference of the team, rather than the team name. Then we'll define the legendItems array and populate it using the assignments retrieved from the attribute group handler.

color: colorHandler.getValue(item.conference)


 

var assignments = colorHandler.getCategoryAssignments();
self.legendItems = [];
for(var i=0; i<assignments.length; i++) {
  self.legendItems.push({
    text: assignments[i].category,
    color: assignments[i].value
  })
}


 

And that will give us the chart below. The same technique can be used to color based on any data dimension or to populate a standalone legend outside of the chart. As for the other two reasons to vary the bar colors, I'll be covering best practices for associated views (multiple visualizations based on common data) and how to assign specific colors (Celtics = Green) while using the attribute group handler in a future post.

barColors3.png