Changing chart series color at run time with a ColorPicker

A recent thread in the Flex support forums resulted in a couple of new charting examples. Specifically, a user was trying to use a ColorPicker component to change the color of a series in a chart at run time. Turns out, it was a little tricky, so I figured I should share the examples.

The first example shows a LineChart. You can click on an item in the chart, which brings up a ColorPicker. You select a color and Flex applies that color to the selected series.

The meat of the example is in the itemClick handler. This is where you get a reference to the LineSeries by accessing the LineSeriesItem’s element property. Here’s the code:

private function selectItemHandler(e:ChartItemEvent):void {
var hitData:HitData = e.hitData;
csi = LineSeriesItem(hitData.chartItem);
el = ChartElement(csi.element);

cp = new ColorPicker();
myChart.addChild(cp);
cp.addEventListener(ColorPickerEvent.CHANGE, changeItemColor);
cp.x = e.localX;
cp.y = e.localY;
cp.open();
}

The changeItemColor() method is pretty straightforward. For a LineChart’s series, you define a new Stroke and then apply that Stroke to the series’ lineStroke style. You then remove the ColorPicker from the display list so it doesn’t pollute the chart’s appearance. Here’s the code for that:

private function changeItemColor(e:ColorPickerEvent):void {
var s1:Stroke = new Stroke(cp.selectedColor, 4, 1);
el.setStyle("lineStroke", s1);
myChart.removeChild(cp);
}

Here’s a running example:

To change the color of a series like a ColumnSeries or a BarSeries, you have to apply the style a little bit differently. In this case, you define a SolidColor and then apply that to the series’ fill property.

var c:SolidColor = new SolidColor(cp.selectedColor);
el.setStyle("fill", c);

Here’s the running example:

The final example is a little different in that it applies the color to a single item in the series and not the entire series. I thought it was interesting, so I figure I’d share it.

Instead of applying a style to the series, you set the fill property on the ColumnSeriesItem:

var c:SolidColor = new SolidColor(cp.selectedColor);
csi.fill = c;

In addition, to get it to work requires a little workaround: You have to trigger a call to the series’ updateDisplayList(). To do that, you just set a property on the itemRenderer, like this:

csi.itemRenderer.height = csi.itemRenderer.height;

Here’s the running example:

Here is a ZIP file of the 3 running examples and the source code:
Download file (985KB)

You might notice that these examples also use the live data that I blogged about recently.

6 Responses to Changing chart series color at run time with a ColorPicker

  1. equ says:

    Very nice example, but there is a little bug:when I click on a chart and do not select any color (click anywhere else) color picker component isn’t removed form the stage.

  2. Jukka Hämäläinen says:

    Hi, nice functionality. Still, I would like to take it one step further. Is it possible to change the color of one lineseries item? So the one line could go (e.g.) from green to yellow and so on?So far my experiments regarding this have been very unsatisfying. :/

  3. Brice says:

    I’ve modified the code above to allow series color change when the user clicks on the corresponding legend icon:<?xml version="1.0"?><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"><mx:Script>&lt;![CDATA[import mx.charts.series.LineSeries;import mx.charts.events.LegendMouseEvent;import mx.events.DropdownEvent;import mx.controls.Alert;import mx.collections.ArrayCollection;import mx.charts.events.ChartItemEvent;import mx.controls.ColorPicker;import mx.events.ColorPickerEvent;import mx.charts.HitData;import mx.charts.chartClasses.ChartElement;import mx.graphics.Stroke;import mx.charts.series.items.LineSeriesItem;private var el:ChartElement;[Bindable]private var chartData:XML = <data><result month="Jan"><profit>2000</profit><expenses>1500</expenses><amount>450</amount></result><result month="Feb"><profit>1000</profit><expenses>200</expenses><amount>600</amount></result><result month="Mar"><profit>1500</profit><expenses>500</expenses><amount>300</amount></result></data>private function selectItem(e:LegendMouseEvent):void {el = ChartElement(e.item.element);cp.x = e.target.x + e.item.x;cp.y = e.target.y + e.item.y;cp.open();}private function changeItemColor(e:ColorPickerEvent):void {var s1:Stroke = new Stroke(cp.selectedColor, 4, 1); //First 3 arguments are color, weight, and alpha.el.setStyle("lineStroke", s1);}]]></mx:Script><mx:Panel title="Line Chart"><mx:LineChart id="myChart"dataProvider="{chartData.result}"showDataTips="true"><mx:horizontalAxis><mx:CategoryAxis categoryField="@month"/></mx:horizontalAxis><mx:series><mx:LineSeriesyField="profit"displayName="Profit"selectable="true"/><mx:LineSeriesyField="expenses"displayName="Expenses"selectable="true"/><mx:LineSeriesyField="amount"displayName="Amount"selectable="true"/></mx:series></mx:LineChart><mx:Legend id="myLegend" itemClick="selectItem(event)" dataProvider="{myChart}"/><mx:ColorPicker id="cp" focusThickness="0" visible="false" opaqueBackground="true" includeInLayout="false" change="changeItemColor(event)"/></mx:Panel></mx:Application>

  4. Brice says:

    And for the bar chart:<?xml version="1.0"?><!– charts/ColumnSeriesItemWithColorPicker.mxml –><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml&quot; creationComplete="srv.send()"><!– View source of the following page to see the structure of the data that Flex uses in this example. –><mx:HTTPService id="srv" url="http://aspexamples.adobe.com/chart_examples/expenses-xml.aspx"/>&lt;!– To see data in an HTML table, go to http://aspexamples.adobe.com/chart_examples/expenses.aspx –><mx:Script><![CDATA[import mx.charts.events.LegendMouseEvent;import mx.collections.ArrayCollection;import mx.charts.events.ChartItemEvent;import mx.controls.ColorPicker;import mx.events.ColorPickerEvent;import mx.charts.HitData;import mx.charts.chartClasses.ChartElement;import mx.charts.series.items.ColumnSeriesItem;import mx.graphics.SolidColor;private var el:ChartElement;private function selectItem(e:LegendMouseEvent):void {el = ChartElement(e.item.element);cp.x = e.target.x + e.item.x;cp.y = e.target.y + e.item.y;cp.open();}private function changeItemColor(e:ColorPickerEvent):void {el.setStyle("fill", cp.selectedColor);}]]></mx:Script><mx:Panel title="Column Chart"><mx:ColumnChart id="myChart"dataProvider="{srv.lastResult.data.result}"showDataTips="true" ><mx:horizontalAxis><mx:CategoryAxiscategoryField="month"/></mx:horizontalAxis><mx:series><mx:ColumnSeriesxField="month"yField="profit"displayName="Profit"selectable="true"/><mx:ColumnSeriesxField="month"yField="expenses"displayName="Expenses"selectable="true"/></mx:series></mx:ColumnChart><mx:Legend id="myLegend" itemClick="selectItem(event)" dataProvider="{myChart}"/><mx:ColorPicker id="cp" focusThickness="0" visible="false" opaqueBackground="true" includeInLayout="false" change="changeItemColor(event)"/></mx:Panel></mx:Application>

  5. Andreas says:

    In example no. 3 csi with colorpicker, why does the csi not “remember” the color which is picked? It look like you can only change a color at once. What has to be done that the color does not change again?

  6. Rajashekhar says:

    How can we do this with Pie chart ???????