Scrolling and zooming chart with CategoryAxis
Title of this post is a little bit misleading because it is not possible to use ChartScroller directly with CategoryAxis. This is because ChartScroller relays on axis minimum/maximum properties which are not present in CategoryAxis. Luckily it is possible to simulate CategoryAxis behavior with LinearAxis which is supported by ChartScroller. I will describe how to do it in this post.
Simple scenario
The simplest and quite common scenario is having one data provider containing objects with single property determining category and further properties determining values of the series. Such data provider may look something like this (code copied from Flex API examples):
[Bindable]
public var dp:ArrayCollection = new ArrayCollection( [
{ Month: "Jan", Profit: 2000, Expenses: 1500, Amount: 450 },
{ Month: "Feb", Profit: 1000, Expenses: 200, Amount: 600 },
{ Month: "Mar", Profit: 1500, Expenses: 500, Amount: 300 },
{ Month: "Apr", Profit: 1800, Expenses: 1200, Amount: 900 },
{ Month: "May", Profit: 2400, Expenses: 575, Amount: 500 } ]);
In such case we have to do three things to simulate CategoryAxis behavior with LinearAxis:
- Declare only yField property of series (not xField).
- Create label function converting data provider index to category name.
- Declare LinearAxis using created label function with interval property set to 1.
Label function may look like this (If xField of series is not specified Flex passes item index as labelValue so all we have to do is find correct item and return category value):
public function categoryLabelFunction(labelValue:Object,
previousValue:Object, axis:IAxis):String
{
var index:int = int(labelValue);
if (index >= 0 && index < dp.length)
return dp[index].Month;
return "";
}
As you can see chart MXML code is only slightly modified compared to code using standard CategoryAxis:
<mx:ColumnChart id="columnChart" width="100%" height="100%"
gutterLeft="50" gutterRight="40" dataProvider="{dp}">
<mx:series>
<!-- Note that xField is not specified -->
<mx:ColumnSeries yField="Profit" />
<mx:ColumnSeries yField="Expenses" />
<mx:ColumnSeries yField="Amount" />
</mx:series>
<mx:horizontalAxis>
<!-- LinearAxis simulating CategoryAxis -->
<mx:LinearAxis interval="1"
labelFunction="categoryLabelFunction" />
</mx:horizontalAxis>
</mx:ColumnChart>
View source is enabled, you can download zipped sources from here.
More complex scenario
In some cases you may need to use xField series properties. For example you may be using separate data providers of different length for different series. In such case additional parse function have to be created to convert category name to numeric value which can be placed along LinearAxis. You can find full example of such scenario here.
View source is enabled, you can download zipped sources from here.
It looks nice. I wonder if ChartScroller will work with dynamic dataProvider binding?
It should work without any problems.
Notice that changing dataProvider will not reset axis minimum/maximum values so if you want a to have axis minimum/maximum values adjusted to data (so that all data are visible) you may have to set them to NaN after dataProvider is changed.
Good afternoon Friend, His/her work was very good… I don’t only know like you would do to put the showDataTips = “true” and to bring the category of each column. Could he/she become trained?
Hi Tiago,
Try using dataTipFunction
http://livedocs.adobe.com/flex/3/langref/mx/charts/chartClasses/ChartBase.html#dataTipFunction
hitData.item should contain data related to the given column so you should be able to extract column name (category) easily.
Hey Iwo,
great work … I am using dataprovider from backend, bt the vertical axis for me shows from 0 to 100 (inspite of me having data greater than 100) … do i have to set some property for the same ..
Thanks,
cheers,
Hi Nimesh,
0/100 is the default minimum/maximum of linear axis. I can’t tell you why this values are preserved without having a look at your code, but I can give you a workaround: Set the vertical axis minimum/maximum values to NaN after dataProvider is changed, this should cause axis range to be adjusted to data.
Hi,
Is it possible to use this on LineChart? I tired and I got vertical line only.
Thanks
Hi Omer,
I tested it on the example above, by changing ColumnChart to LineChart and ColumnSeries to LineSeries, and it works.
Only horizontal axis looks different, but previous look can be restored by setting
horizontalAxisStyleName="blockNumericAxis"on LineChart or by creating axis renderer withstyleName="blockNumericAxis".Can any one let me know how to prevent the X-axis scrolling if there is no data further or earlier than first node?
Because it is continue to scrolling even if there is no data?
Thanks in Advance.
For now there is no such feature. In my project we quite often scroll beyond the data and than fetch remaining data. It would be possible to define global minimum/maximum which will block further scrolling but I don’t have time to do it… I’ve just changed the job and moved and I’m really busy…
hi, you wrote nice code it helps me a lot. but i find a small problem. Replace dataprovider to the following and find some undesired results.
[Bindable]
public var dp:ArrayCollection = new ArrayCollection
([{ Month: "Jan", Profit: 2000} ]);
you will find that loop goes on some 100 times(100 traces) and chart includes only 1 thin line on left hand side corner.
Hi,
I’ve tried your code on a LineChart, and it works amazingly. I’ve modified the labelFunction and parseFunction for the horizontal axis in order to get a DD/MM dateformat. Unfortunately, I got a disturbing issue : when I ZoomOut too much, the order of my dates is inversed (from right to left) whereas the Graph stays the same… What sould I do?
Thank you in advance