There might be a situation where you would want to stack 2 different set of column data together. (For example, you are managing a toys department and you wanted to show the total of the number of toy cars and toy aeroplane that you have sold on that day. On top of that, you also want to find out the breakdown of the number of toy cars and toy aeroplanes that you have sold that particular day.) So how to stack all the column data together? Here's a simple example that I have created.
Here's the source code of my main application - SimpleStackingColumn.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; //Adding the values of all the series together tempObj.data = Number(myData.record[i].people) + Number(myData.record[i].car); //Create a new object for the data tooltip 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 = "data"; 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"; 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; //Don't need to adding the values of all the //series together tempObj.data = myData.record[i].car; //Create a new object for the data tooltip 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 = "data"; 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"; //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(localSeries); currentSeries.push(localCarSeries); // 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; } ]]> </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: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