Well, I was trying to figure out how to render multiple column chart some time back. After spending a few days playing around it, I finally found a way to work around it. :)
Tim for some source files - 'SimpleMultipleColumn.mxml'<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
backgroundColor="#CDCDCD"
creationComplete="creationCompleteEvent(event)">
<fx:Declarations>
<!--
We need to specify the types of animations over here
-->
<s:Parallel id="parallelEffect">
<s:Fade duration="1000" alphaFrom="0" alphaTo="1"/>
<mx:SeriesSlide duration="1000" direction="up"/>
</s:Parallel>
<s:Parallel id="parallelCarEffect">
<s:Fade duration="1000" alphaFrom="0" alphaTo="1"/>
</s:Parallel>
</fx:Declarations>
<fx:Script>
<![CDATA[
import flashx.textLayout.conversion.TextConverter;
import mx.charts.HitData;
import mx.charts.chartClasses.IChartElement2;
import mx.charts.chartClasses.Series;
import mx.charts.series.ColumnSeries;
import mx.charts.series.LineSeries;
import mx.collections.ArrayCollection;
import mx.collections.Sort;
import mx.collections.SortField;
import mx.events.FlexEvent;
import mx.formatters.DateFormatter;
import mx.graphics.Stroke;
import spark.events.IndexChangeEvent;
//Records used in the chart
[Bindable]
private var myData:XML =
<records>
<record>
<date>01/09/2013</date>
<people>63</people>
<car>23</car>
</record>
<record>
<date>02/09/2013</date>
<people>61</people>
<car>81</car>
</record>
<record>
<date>03/09/2013</date>
<people>67</people>
<car>47</car>
</record>
<record>
<date>04/09/2013</date>
<people>75</people>
<car>95</car>
</record>
<record>
<date>05/09/2013</date>
<people>65</people>
<car>45</car>
</record>
<record>
<date>06/09/2013</date>
<people>32</people>
<car>52</car>
</record>
<record>
<date>07/09/2013</date>
<people>66</people>
<car>46</car>
</record>
<record>
<date>08/09/2013</date>
<people>85</people>
<car>105</car>
</record>
<record>
<date>09/09/2013</date>
<people>37</people>
<car>57</car>
</record>
<record>
<date>10/09/2013</date>
<people>80</people>
<car>100</car>
</record>
</records>;
private var localSeries:ColumnSeries = new ColumnSeries();
private var localCarSeries:ColumnSeries = new ColumnSeries();
protected function creationCompleteEvent(event:FlexEvent):void
{
//Create the SortField object for the "time" field in
//the ArrayCollection object, and make sure we do a
//numeric sort.
var dataSortField:SortField = new SortField();
dataSortField.name = "time";
dataSortField.numeric = true;
//Create the Sort object and add the SortField object
//created earlier to the array of fields to sort on.
var numericDataSort:Sort = new Sort();
numericDataSort.fields = [dataSortField];
// Parsing the xml data into ArrayCollection
var objArray:ArrayCollection = new ArrayCollection();
var tempObj:Object;
var dateArray:Array;
var tempDate:Date;
for(var i:int = 0; i < myData.record.length(); i ++)
{
tempObj = new Object();
dateArray = String(myData.record[i].date).split("/");
//Convert the date data into a Date Object
tempDate = new Date(dateArray[2],
Number(dateArray[1]) - 1,
dateArray[0]);
tempObj.date = tempDate;
tempObj.time = tempDate.time;
tempObj.people = myData.record[i].people;
tempObj.label = dateFormatter(tempDate);
objArray.addItem(tempObj);
}
objArray.sort = numericDataSort;
objArray.refresh();
//Create the new series and set its properties.
localSeries.dataProvider = objArray;
localSeries.yField = "people";
localSeries.xField = "date";
//Create alternate colors for the columns
localSeries.setStyle("fill", 0xCDFFCD);
//Create the strokes for the columns
localSeries.setStyle("stroke",
new Stroke(0xFFFFFF, 0.1, 0.5));
localSeries.displayName = "col_people";
//Set the width(%) of the column
localSeries.columnWidthRatio = 0.3;
//Set the offset
localSeries.offset = -0.15;
objArray = new ArrayCollection();
for(i = 0; i < myData.record.length(); i ++)
{
tempObj = new Object();
dateArray = String(myData.record[i].date).split("/");
//Convert the date data into a Date Object
tempDate = new Date(dateArray[2],
Number(dateArray[1]) - 1,
dateArray[0]);
tempObj.date = tempDate;
tempObj.time = tempDate.time;
tempObj.car = myData.record[i].car;
tempObj.label = dateFormatter(tempDate);
objArray.addItem(tempObj);
}
objArray.sort = numericDataSort;
objArray.refresh();
//Create the new series and set its properties.
localCarSeries.dataProvider = objArray;
localCarSeries.yField = "car";
localCarSeries.xField = "date";
//Create alternate colors for the columns
localCarSeries.setStyle("fill", 0xCDCDFF);
//Create the strokes for the columns
localCarSeries.setStyle("stroke",
new Stroke(0xFFFFFF, 0.1, 0.5));
localCarSeries.displayName = "line_car";
//Set the width(%) of the column
localCarSeries.columnWidthRatio = 0.3;
//Set the offset
localCarSeries.offset = 0.15;
//We will remove all the series attach to the chart
//first
chart.series = null;
//End all the effects first, else some glich will
//appear.
parallelEffect.end();
parallelCarEffect.end();
//Base on the type of animation selected, attach
//the effect to the column
localSeries.setStyle("creationCompleteEffect",
parallelEffect);
localCarSeries.setStyle("creationCompleteEffect",
parallelCarEffect);
// Back up the current series on the chart.
var currentSeries:Array = chart.series;
// Add the new series to the current Array of series.
currentSeries.push(localCarSeries);
currentSeries.push(localSeries);
// Add the new Array of series to the chart.
chart.series = currentSeries;
}
//This function will return a string based on the
//Date format DD/MM/YYYY.
private function dateFormatter(tempDate:Date):String
{
var fmt:DateFormatter = new DateFormatter();
fmt.formatString = "DD/MM/YYYY";
return fmt.format(tempDate);
}
//We are customizing the datatip / tool tip of the
//chart data.
public function myDataTipFunction(e:HitData):String {
var s:String = "";
var tempDate:Date = e.item.date as Date;
s += "Date: " + dateFormatter(tempDate) + "<br>";
if(Series(e.element).displayName == "col_people")
{
s += "No. of People: " + e.item.people;
}else{
s += "No. of Cars: " + e.item.car;
}
return s;
}
//This function will be used to change the date labels of
//the chart to match the data.
public function createDate(s:Date):Date {
var newDate:Date = new Date();
newDate.time = s.time;
//We need to increase a day to the labels.
newDate.date += 1;
return newDate;
}
//This function will toggle the visibility of the chart
//Data based on the values of the respective check boxes.
protected function chkChartChangeEvent(event:Event):void
{
var showCarData:Boolean = chkCar.selected;
var showPeopleData:Boolean = chkPeople.selected;
for(var i:int = 0; i < chart.series.length; i ++)
{
if(chart.series[i].displayName == "line_car")
{
chart.series[i].visible = showCarData;
}
if(chart.series[i].displayName == "col_people")
{
chart.series[i].visible = showPeopleData;
}
}
}
]]>
</fx:Script>
<s:VGroup width="100%"
height="100%"
verticalAlign="middle"
horizontalAlign="center">
<s:BorderContainer width="100%"
backgroundAlpha="0"
borderVisible="false">
<s:HGroup verticalAlign="middle" horizontalAlign="center"
width="100%"
height="100%">
<!-- Need to set the gutterLeft and
gutterTop of the chart -->
<mx:CartesianChart id="chart"
gutterTop="0"
gutterLeft="50"
showDataTips="true"
width="80%"
height="80%"
dataTipFunction="myDataTipFunction">
<mx:horizontalAxis>
<mx:DateTimeAxis dataUnits="days" id="dateAxis"
alignLabelsToUnits="false"
parseFunction="createDate"/>
</mx:horizontalAxis>
</mx:CartesianChart>
</s:HGroup>
</s:BorderContainer>
<s:HGroup width="100%" horizontalAlign="center"
verticalAlign="middle">
<s:CheckBox id="chkCar"
change="chkChartChangeEvent(event)"
selected="true"
label="Show Car Data"/>
<s:CheckBox id="chkPeople"
change="chkChartChangeEvent(event)"
selected="true"
label="Show People Data"/>
</s:HGroup>
</s:VGroup>
</s:Application>
* Click here for the demo shown in this post.^ Click here for the source files for the demo.
No comments:
Post a Comment