FLEX: how to dynamically add LineSeries to CartesianChart - apache-flex

the LineSeries is not dynamically added to my CartesianChart...
What's wrong in this code:
...
private function chartComplete():void {
var ls:LineSeries = new LineSeries();
ls.styleName = 'timeline';
ls.dataProvider = "{dataManager.tagViewTimelineModel.tags.getItemAt(0).yearPopularity}";
ls.yField = 'popularity';
//ls.s = "{new Stroke(0xCC33CC, 2)}";
AllChart.series[0] = ls;
}
...
<mx:CartesianChart id="AllChart" width="100%" height="100" creationComplete="chartComplete();">
<mx:horizontalAxis><mx:CategoryAxis id="horiz1" dataProvider="['1','2','3','4','5','6','7','8','9','10','11','23','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31']"/></mx:horizontalAxis>
<mx:horizontalAxisRenderers><mx:AxisRenderer axis="{horiz1}"/></mx:horizontalAxisRenderers>
<mx:verticalAxis><mx:LinearAxis id="vert1" /></mx:verticalAxis>
<mx:verticalAxisRenderers><mx:AxisRenderer axis="{vert1}"/></mx:verticalAxisRenderers>
<mx:series>
<mx:AreaSeries id="timeArea" styleName="timeArea" name="A" dataProvider="{dataManager.tagViewTimelineModel.tags.getItemAt(2).yearPopularity}" areaStroke="{new Stroke(0x0033CC, 2)}" areaFill="{new SolidColor(0x0033CC, 0.5)}" />
</mx:series>
</mx:CartesianChart>
I can only see the TimeLine if I added it with MXML:
<mx:LineSeries styleName="timeLine" dataProvider="{dataManager.tagViewTimelineModel.tags.getItemAt(0).yearPopularity}" yField="popularity" stroke="{new Stroke(0xCC33CC, 2)}" />
But I need to update the view, and add N lines so I cannot do it with MXML.
thanks

You can set the series property for the chart. Just add a new Series object to that array.

Related

Timeline in Flex

Trying to build a timeline in Flex, Have a horizontal slider when i slide the slider there should be a line on the linechart as a needle moving with respect to value of slider,I Tried using gridlines to achieve this but the grid lines are visible across all the values of x axis,But I want to show only single gridline with respect to value of slider. Is there a way to hide few grid lines and show specific gridlines.
Here's something I created in about 30 minutes. It's very rudimentary, and has some issues that I will leave for you to solve (or you can post a new question specific to the remaining issues). It's likely you'll need to modify this to suit your application anyway, so I didn't bother looking at the remaining issues.
I've assumed you're using Date objects for the horizontal axis of the chart. As such you need to convert the date object to it's corresponding numerical value (in epoch time). This allows you to work with the slider component, which expects numbers.
If you do have further questions, I recommend trying to post whatever code you're using (or a simple version of it), that others can run. That way the answers you get will be specific to your case, and not generic like this one :)
<?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"
creationComplete="onCreationComplete()">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import spark.primitives.Line;
[Bindable] private var chartData : ArrayCollection =
new ArrayCollection(
[
{ sales: 101000, month: new Date( '01/01/2013' ) },
{ sales: 350000, month: new Date( '02/01/2013' ) },
{ sales: 475000, month: new Date( '03/01/2013' ) },
{ sales: 425000, month: new Date( '04/01/2013' ) }
] );
private var line:Line;
private function onCreationComplete():void
{
line = new Line();
line.height = chart.height;
line.stroke = new SolidColorStroke(0x0000FF, 2);
chartContainer.addElement(line); }
private function getDateInEpochTime(date:Date):Number
{
return date.time;
}
private function dataTipFormatFunction(value:Number):Object
{
return new Date(value).toString();
}
private function onSliderChange():void
{
line.x = convertSliderValueToXCoordinate();
}
private function convertSliderValueToXCoordinate():Number
{
var min:Number = slider.minimum;
var max:Number = slider.maximum;
var adjustedValue:Number = slider.value - min;
var range:Number = max - min;
var percentOfRange:Number = adjustedValue/range
var xCoordinate:Number = slider.width * percentOfRange;
var thumbWidth:Number = slider.thumb.width;
if (percentOfRange > .5)
xCoordinate = xCoordinate - (thumbWidth * (percentOfRange - .5));
else if (percentOfRange < .5)
xCoordinate = xCoordinate + (thumbWidth * (.5 - percentOfRange));
return xCoordinate;
}
]]>
</fx:Script>
<s:Group id="chartContainer" width="800" height="600">
<mx:LineChart id="chart" dataProvider="{chartData}" left="0" right="0" top="0" bottom="20">
<mx:horizontalAxis>
<mx:DateTimeAxis id="hAxis" dataUnits="months" alignLabelsToUnits="true" displayLocalTime="true"/>
</mx:horizontalAxis>
<mx:series>
<mx:LineSeries displayName="Sales by Month" yField="sales" xField="month">
<mx:lineStroke>
<s:SolidColorStroke color="0xFF0000" />
</mx:lineStroke>
</mx:LineSeries>
</mx:series>
</mx:LineChart>
<s:HSlider id="slider" left="0" right="0" bottom="0"
dataTipFormatFunction="dataTipFormatFunction"
minimum="{getDateInEpochTime(chartData.getItemAt(0).month)}"
maximum="{getDateInEpochTime(chartData.getItemAt( chartData.length -1 ).month)}"
change="onSliderChange()"/>
</s:Group>
</s:Application>

LineChart data tip won't display with single data point?

In Flex 3, I have a line chart.
My data provider for the line chart contains only one item.
When I draw the line chart, it plots the point. But it doesn't show the data tip.
It works if more than one item is present in dataprovider.
How can I make a data tip visible for line chart with dataprovider containing a single data item?
Use PlotSeries instead of LineSeries when you only have one point. You will get a nice round point with its dataTip. How to do it exactly depends on how your data is built - if the data doesn't change after being assigned to the dataProvider, you can choose which type of series to use at that moment.
try the following code,
in actionscript,
lineSeries.setStyle("itemRenderer", new ClassFactory(mx.charts.renderers.CircleItemRenderer));
in mxml,
<mx:LineSeries yField="Y" itemRenderer="mx.charts.renderers.CircleItemRenderer" xField="X" dataProvider="{lineDataProvider}">
There is a workaround to show the datatip. We need to add ROLL_OVER and ROLL_OUT mouse event listeners to the line series which has single datapoint.
<?xml version="1.0"?>
<!-- Simple example to demonstrate the LineChart and AreaChart controls. -->
<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">
<fx:Script>
<![CDATA[
import mx.charts.HitData;
import mx.charts.renderers.*;
import mx.charts.series.items.LineSeriesItem;
import mx.collections.ArrayCollection;
[Bindable]
private var expensesAC:ArrayCollection = new ArrayCollection( [
{ Month: "Jan", Profit: 2000 } ]);
private function lineseriesRollOverHandler(event:MouseEvent):void
{
linechart.showAllDataTips = true;
}
private function lineserieRollOutHandler(event:MouseEvent):void
{
linechart.showAllDataTips = false;
}
private function dataTipFunction(hitData:HitData):String
{
if(hitData && hitData.item)
{
var s:String = "";
if(hitData.element is LineSeries)
{
if(expensesAC.length <=1)
hitData.x = 56;
var lsi:LineSeriesItem = hitData.chartItem as LineSeriesItem;
if(lsi == null)
return "";
s += "<b>" + (hitData.element as LineSeries).displayName + "</b><br />";
s += lsi.xValue + "<br />";
s += lsi.yNumber;
}
return s;
}
return "";
}
]]>
</fx:Script>
<fx:Declarations>
</fx:Declarations>
<mx:Panel width="100%" height="100%" layout="horizontal" title="Single point LineChart Example">
<mx:LineChart id="linechart" width="45%" height="100%" dataProvider="{expensesAC}"
paddingLeft="5" paddingRight="5" showDataTips="true" dataTipFunction="dataTipFunction">
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="Month"/>
</mx:horizontalAxis>
<mx:series>
<mx:LineSeries displayName="Profit" form="curve"
itemRenderer="mx.charts.renderers.CircleItemRenderer"
legendMarkerRenderer="mx.charts.renderers.BoxItemRenderer"
rollOut="lineserieRollOutHandler(event)"
rollOver="lineseriesRollOverHandler(event)" yField="Profit"/>
</mx:series>
</mx:LineChart>
<mx:Legend dataProvider="{linechart}"/>
</mx:Panel>
</s:Application>

Flex3: How to "Re-load" A Component

How do I, in effect, "reset" a component in order to have it look the the way it did when it first loaded. For example, I've got 3 buttons in an HBox. They start as red, visible, and have a label. I then programmatically make different changes to them-- change the color of some of them, change the visibility of some of them, etc.
I then need to "reload" this HBox, have it revert back to the way it looked at the start. Is there an easy way to do this? (I have a lot of components that need to be changed).
<mx:HBox>
<mx:Button id="button1"
label="button1"
fillColors="[red, red]"
toggle="true" click="myClickHandler"/>
<mx:Button id="button2"
label="button1"
fillColors="[red, red]"
toggle="true" click="myClickHandler"/>
<mx:Button id="button3"
label="button1"
fillColors="[red, red]"
toggle="true" click="myClickHandler"/>
</mx:HBox>
If you have a suggestion, please let me know. Thank you.
-Laxmidi
You are already problematically changing this code at runtime. Just write a method to change it back to it's default state. That is probably what I'd do.
Alternately, if this is an encapsulated component, you could always remove it with removeChild, create another instance, and put that new one in the same place.
Per comments, here is some psuedo code for looping over children of a component and changing properties:
for (var i : int =0; i<hBox.numChildren; i++){
var child : UIComponent = hBox.getChildAt(i);
child.setStyle('style','defaultValue');
child.property = 'default value'
}
<mx:Application>
<mx:Script>
private function onColorChange():void
{
can.removeAllChildren();
var loader:Loader = new Loader();
loader.load(new URLRequest('assets/images/logo/1.png'));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onComplete);
/* image= new Image();
image.source = "assets/images/logo/1.jpg";
image.setStyle('horizontalCenter','0');
image.setStyle('verticalCenter','0'); */
//can.addChild(image);
txt= new Text();
txt.text = "Ankur sharma";
txt.styleName = "font";
txt.setStyle('fontFamily','Anime Ace');
txt.rotation = -10;
can.addChild(txt);
can.mask = txt;
//applyFilter(CC.uint2rgb(cp.selectedColor));
}
private function onComplete(event:Event):void
{
rect = new Rectangle();
rect = txt.getBounds(can);
can.graphics.clear();
can.graphics.beginBitmapFill(event.currentTarget.content.bitmapData);
can.graphics.drawRect(rect.x,rect.y,rect.width,rect.height);
can.graphics.endFill();
}
</mx:Script>
<mx:ColorPicker id="cp" change="onColorChange()"/>
<mx:Canvas id="can" height="100%" horizontalCenter="0" verticalCenter="0" borderStyle="solid" borderColor="#CCCCCC" borderThickness="5">
<mx:Image source="assets/images/logo/1.png" horizontalCenter="0" verticalCenter="0"/>
<mx:Text text="Ankur Sharma" styleName="font" rotation="-10"/>
</mx:Canvas>
<mx:Style source="style.css"/>
</mx:Application>
in this example, wht i m doin is i m removing all children in ma canvas(id=can) amd then then makeing n e changes, to exizting components and then adding thm back to the canvas,
this program is of masking n e ways, my canvas has two children, and i m putting ma text as a mask over the canvas, and i am filling the canva with bitmap image, thats it
i hop it hepls

FLEX: areaSeries is empty

I want to use an AreaSeries to display the content of an arrayCollection (the cell values are displayed on the y axis).
The Array collection is dataManager.tagViewTimelineModel.summedPopularity
<mx:AreaSeries id="timeArea" styleName="timeArea" name="A" dataProvider="dataManager.tagViewTimelineModel.summedPopularity" areaStroke="{new Stroke(0x0033CC, 2)}" areaFill="{new SolidColor(0x0033CC, 0.5)}" />
But it doesn't work, the graph is empty....
Am I doing something wrong ?
This is the full code for completeness.
mx:CartesianChart id="AllChart" dataProvider="{dataManager.tagViewTimelineModel.tags}" width="100%" height="100">
<mx:horizontalAxis><mx:CategoryAxis id="horiz1" dataProvider="['1','2','3','4','5','6','7','8','9','10','11','23','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31']"/></mx:horizontalAxis>
<mx:horizontalAxisRenderers><mx:AxisRenderer axis="{horiz1}"/></mx:horizontalAxisRenderers>
<mx:verticalAxis><mx:LinearAxis id="vert1" /></mx:verticalAxis>
<mx:verticalAxisRenderers><mx:AxisRenderer axis="{vert1}"/></mx:verticalAxisRenderers>
<mx:series>
<mx:AreaSeries id="timeArea" styleName="timeArea" name="A" dataProvider="dataManager.tagViewTimelineModel.summedPopularity" areaStroke="{new Stroke(0x0033CC, 2)}" areaFill="{new SolidColor(0x0033CC, 0.5)}" />
</mx:series>
</mx:CartesianChart>
thanks
I think you might need { } around your dataProvider for your AreaSeries declaration. You have it on top for your chart but you probably overrode it below.

Filtering data shown on linechart in flex

i am working on a line chart on flex which enable me to view the progress of data according to the year. I have tried using a slider to filter but it doesn't seemed to work. any help please?
i am not exactly filtering the dataprovider, but the alpha. My function will retrieve all the information from my array collection, but set the alpha to 0, so when user drags the slider, if the year falls below that particular year, it will display the data, which i then set the alpha to 100.
The data is there, the axis are all set, alpha is set to 0. but the problem is, it doesn't display the information line by line as what i wanted it to be, instead, it display the whole graph only until i drag the slider to the end...
these are my codes
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Year:"1990", Profit:2000 },
{Year:"1991", Profit:1000 },
{Year:"1992", Profit:1500 },
{Year:"1993", Profit:2100 },
{Year:"1994", Profit:2500 },
{Year:"1995", Profit:1500 },
{Year:"1996", Profit:1900 },
]);
private function init():void {
expenses.filterFunction = sliderFilterFunc;
expenses.refresh();
}
private function sliderFilterFunc(item:Object):Boolean{
var result:Boolean = true;
pro.alpha=0;
if(item.Year<=slider.value || item.Year==slider.value)
{
pro.alpha=100;
return result;
}
return result;
}
]]></mx:Script>
<mx:VBox horizontalCenter="0" top="10" horizontalAlign="center" height="100%">
<mx:HSlider id="slider" minimum="1990" maximum="1996" value="220" liveDragging="true" change="init()" width="570" snapInterval="1" dataTipPrecision="0" labels="['1990','1996']" tickInterval="1" themeColor="#000000" borderColor="#FFFFFF" fillAlphas="[1.0, 1.0, 1.0, 1.0]" fillColors="[#000000, #000000, #FFFFFF, #1400D1]" height="48" styleName="myDataTip"/>
<mx:Panel title="Line Chart with One Shadow">
<mx:LineChart id="myChart" dataProvider="{expenses}" showDataTips="true" >
<mx:seriesFilters>
<mx:Array/>
</mx:seriesFilters>
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Year"
/>
</mx:horizontalAxis>
<mx:series>
<mx:LineSeries id="pro" alpha="0"
yField="Profit"
displayName="Profit"
/>
</mx:series>
</mx:LineChart>
<mx:Legend dataProvider="{myChart}" />
</mx:Panel>
</mx:VBox>
</mx:Application>
sorry for the messiness.:(
You seem to be using dates as your x axis, the slider can "slide" between numeric values.
What I would do is make my expenses ArrayCollection to:
public var expenses:ArrayCollection = new ArrayCollection([
{Year: new Date(1990), Profit:2000 },
{Year: new Date(1991), Profit:1000 },
...
Then for your filter function:
private function sliderFilterFunc(item:Object):Boolean {
pro.alpha = item.Year.getTime() <= slider.value ? 100 : 0;
return true;
}
Also, are you sure you want to set the alpha to 0 instead of just filtering out the data points? If you would like to shrink your ArrayCollection (don't worry this shrinks the ArrayCollection, not the source, the Array), you could just do:
private function sliderFilterFunc(item:Object):Boolean {
return = item.Year.getTime() <= slider.value;
}
Finally, you should also set your own dataTipFunction for the slider so instead of seeing numbers they see the actual date.
i created a Flex Library (DataFilterLib) that take care of all the filtering process, completly in MXML.
This library is free, you can find the project details there:
http://code.google.com/p/flex-datafilterlib/
If you want to have a look at the examples, they are all in the project's page (source available):
Check the examples online if you want to see how to filter on multiple criterias, using different Flex UI Components (CheckBox, Slider, List, ...).
Using these filters with a Slider (2-thumbs), you can easily filter your data and it will be automatically reflected on your Chart.
Thanks,
Fabien

Resources