A ChartItem object represents a data point in a series. There is one ChartItem instance for each item in the series' data provider. ChartItem objects contain details about the data for the data point as well as the renderer (or skin) to use when rendering that data point in the series. The ChartItem renderers define objects such as the icon that represents a data point in a PlotChart control or the box that makes up a bar in a BarChart control.
Each series has a default renderer that Flex uses to draw that series' ChartItem objects. You can specify a new renderer to use with the series' itemRenderer style property. This property points to a class that defines the appearance of the ChartItem object.
The following table lists the available renderer classes for the ChartItem objects of each chart type:
|
Chart type |
Available renderer classes |
|---|---|
The appearance of most renderers is self-explanatory. The BoxItemRenderer class draws ChartItem objects in the shape of boxes. The DiamondItemRenderer class draws ChartItem objects in the shape of diamonds. The ShadowBoxItemRenderer and ShadowLineRenderer classes add shadows to the ChartItem objects that they draw.
You can use existing classes to change the default renderers of chart items. The DiamondItemRenderer class is the default renderer for ChartItem objects in a data series in a PlotChart control. The following example uses the default DiamondItemRenderer class for the first data series. The second series uses the CircleItemRenderer class, which draws a circle to represent the data points in that series. The third series uses the CrossItemRenderer class, which draws a cross shape to represent the data points in that series.
<?xml version="1.0"?>
<!-- charts/PlotRenderers.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"January", Profit:2000, Expenses:1500, Amount:450},
{Month:"February", Profit:1000, Expenses:200, Amount:600},
{Month:"March", Profit:1500, Expenses:500, Amount:300},
{Month:"April", Profit:500, Expenses:300, Amount:500},
{Month:"May", Profit:1000, Expenses:450, Amount:250},
{Month:"June", Profit:2000, Expenses:500, Amount:700}
]);
]]></mx:Script>
<mx:Panel title="Plot Chart">
<mx:PlotChart id="myChart"
dataProvider="{expenses}"
showDataTips="true"
>
<mx:series>
<!-- First series uses default renderer. -->
<mx:PlotSeries
xField="Expenses"
yField="Profit"
displayName="Plot 1"
/>
<!-- Second series uses CircleItemRenderer. -->
<mx:PlotSeries
xField="Amount"
yField="Expenses"
displayName="Plot 2"
itemRenderer="mx.charts.renderers.CircleItemRenderer"
/>
<!-- Third series uses CrossItemRenderer. -->
<mx:PlotSeries
xField="Profit"
yField="Amount"
displayName="Plot 3"
itemRenderer="mx.charts.renderers.CrossItemRenderer"
/>
</mx:series>
</mx:PlotChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
</mx:Application>
The executing SWF file for the previous example is shown below:
To apply a renderer to a series in ActionScript, you use the setStyle() method. In that method, you create a new ClassFactory and pass the renderer to its constructor. Flex generates an instance of this class to be the renderer. Be sure to import the appropriate classes when using renderer classes.
The following example sets the renderer for the second series to the CircleItemRenderer and the renderer for the third series to the CrossItemRenderer in ActionScript.
<?xml version="1.0"?>
<!-- charts/PlotRenderersAS.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="initSeriesStyles()">
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
import mx.charts.renderers.*;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"January", Profit:2000, Expenses:1500, Amount:450},
{Month:"February", Profit:1000, Expenses:200, Amount:600},
{Month:"March", Profit:1500, Expenses:500, Amount:300},
{Month:"April", Profit:500, Expenses:300, Amount:500},
{Month:"May", Profit:1000, Expenses:450, Amount:250},
{Month:"June", Profit:2000, Expenses:500, Amount:700}
]);
private function initSeriesStyles():void {
// Second series uses CircleItemRenderer.
series2.setStyle("itemRenderer", new ClassFactory(mx.charts.renderers.CircleItemRenderer));
// Third series uses CrossItemRenderer.
series3.setStyle("itemRenderer", new ClassFactory(mx.charts.renderers.CrossItemRenderer));
}
]]></mx:Script>
<mx:Panel title="Plot Chart">
<mx:PlotChart id="myChart"
dataProvider="{expenses}"
showDataTips="true"
>
<mx:series>
<mx:PlotSeries
id="series1"
xField="Expenses"
yField="Profit"
displayName="Plot 1"
/>
<mx:PlotSeries
id="series2"
xField="Amount"
yField="Expenses"
displayName="Plot 2"
/>
<mx:PlotSeries
id="series3"
xField="Profit"
yField="Amount"
displayName="Plot 3"
/>
</mx:series>
</mx:PlotChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
</mx:Application>
The executing SWF file for the previous example is shown below:
You can sometimes choose from more than one renderer for a chart series, depending on the series. These renderers let you change the appearance of your charts by adding shadows or graphics to the chart items.
Some series types require multiple renderers to completely render their data. For example, a LineSeries object has both an itemRenderer style property and a lineSegmentRenderer style property. The itemRenderer property specifies the renderer for the data items. The lineSegmentRenderer specifies the appearance of the line segments between items.
The other series type that requires two renderers is the AreaSeries. The areaRenderer property specifies the appearance of the area, and the itemRenderer specifies the appearance of the data items.
You can also specify the renderer to use for legends. The default is the class that the series' itemRenderer property specifies. For more information, see Formatting Legend controls.
You can use multiple types of data series in a single chart. For example, you can use a ColumnSeries and a LineSeries to show something like a moving average over a stock price. In this case, you can use all the renderers supported by those series in the same chart. For more information on using multiple series, see Using multiple data series.
You can replace the itemRenderer property of a chart series with a custom renderer. You define the renderer on the itemRenderer style property for the chart series. This renderer can be a graphical renderer or a class that programmatically defines the renderer.
You can use a graphic file such as a GIF or JPEG to be used as a renderer on the chart series. You do this by setting the value of the itemRenderer style property to be an embedded image. This method of graphically rendering chart items is similar to the graphical skimming method used for other components, as described in Creating graphical skins.
The following example uses the graphic file to represent data points on a PlotChart control:
<?xml version="1.0"?>
<!-- charts/CustomPlotRenderer.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"January", Profit:2000, Expenses:1500, Amount:450},
{Month:"February", Profit:1000, Expenses:200, Amount:600},
{Month:"March", Profit:1500, Expenses:500, Amount:300},
{Month:"April", Profit:500, Expenses:300, Amount:500},
{Month:"May", Profit:1000, Expenses:450, Amount:250},
{Month:"June", Profit:2000, Expenses:500, Amount:700}
]);
]]></mx:Script>
<mx:Panel title="Plot Chart">
<mx:PlotChart id="myChart"
dataProvider="{expenses}"
showDataTips="true"
>
<mx:series>
<!-- First series uses embedded image for renderer. -->
<mx:PlotSeries
xField="Expenses"
yField="Profit"
displayName="Plot 1"
itemRenderer="@Embed(source='../assets/butterfly.gif')"
radius="20"
legendMarkerRenderer="@Embed(source='../assets/butterfly.gif')"
/>
<!-- Second series uses DiamondItemRenderer. -->
<mx:PlotSeries
xField="Amount"
yField="Expenses"
displayName="Plot 2"
itemRenderer="mx.charts.renderers.CircleItemRenderer"
/>
<!-- Third series uses CrossItemRenderer. -->
<mx:PlotSeries
xField="Profit"
yField="Amount"
displayName="Plot 3"
itemRenderer="mx.charts.renderers.CrossItemRenderer"
/>
</mx:series>
</mx:PlotChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
</mx:Application>
The executing SWF file for the previous example is shown below:
This example uses the butterfly.gif graphic to represent each data point on the plot chart. It controls the size of the embedded image by using the radius style property.
You are not required to set the value of the itemRenderer property inline. You can also embed a graphic file in ActionScript as a Class, pass it to the ClassFactory class's constructor, and then reference it inline, as the following example shows:
<?xml version="1.0"?>
<!-- charts/CustomPlotRendererAS.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
import mx.core.BitmapAsset;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"January", Profit:2000, Expenses:1500, Amount:450},
{Month:"February", Profit:1000, Expenses:200, Amount:600},
{Month:"March", Profit:1500, Expenses:500, Amount:300},
{Month:"April", Profit:500, Expenses:300, Amount:500},
{Month:"May", Profit:1000, Expenses:450, Amount:250},
{Month:"June", Profit:2000, Expenses:500, Amount:700}
]);
[Bindable]
[Embed(source="../assets/butterfly.gif")]
public var myButterfly:Class;
[Bindable]
public var myButterflyFactory:ClassFactory = new ClassFactory(myButterfly);
]]></mx:Script>
<mx:Panel title="Plot Chart">
<mx:PlotChart id="myChart"
dataProvider="{expenses}"
showDataTips="true"
>
<mx:series>
<!-- First series uses custom class renderer. -->
<mx:PlotSeries
id="series1"
xField="Expenses"
yField="Profit"
displayName="Plot 1"
itemRenderer="{myButterflyFactory}"
legendMarkerRenderer="{myButterflyFactory}"
radius="20"
/>
<!-- Second series uses DiamondItemRenderer. -->
<mx:PlotSeries
id="series2"
xField="Amount"
yField="Expenses"
displayName="Plot 2"
itemRenderer="mx.charts.renderers.CircleItemRenderer"
/>
<!-- Third series uses CrossItemRenderer. -->
<mx:PlotSeries
id="series3"
xField="Profit"
yField="Amount"
displayName="Plot 3"
itemRenderer="mx.charts.renderers.CrossItemRenderer"
/>
</mx:series>
</mx:PlotChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
</mx:Application>
The executing SWF file for the previous example is shown below:
You can also use the setStyle() method to apply the custom class to the item renderer. The following example sets the itemRenderer and legendMarkerRenderer style properties to the embedded image:
<?xml version="1.0"?>
<!-- charts/CustomPlotRendererStyles.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="setStylesInit()">
<mx:Script><![CDATA[
import mx.collections.ArrayCollection;
import mx.core.BitmapAsset;
[Bindable]
public var expenses:ArrayCollection = new ArrayCollection([
{Month:"January", Profit:2000, Expenses:1500, Amount:450},
{Month:"February", Profit:1000, Expenses:200, Amount:600},
{Month:"March", Profit:1500, Expenses:500, Amount:300},
{Month:"April", Profit:500, Expenses:300, Amount:500},
{Month:"May", Profit:1000, Expenses:450, Amount:250},
{Month:"June", Profit:2000, Expenses:500, Amount:700}
]);
[Bindable]
[Embed(source="../assets/butterfly.gif")]
public var myButterfly:Class;
private function setStylesInit():void {
series1.setStyle("itemRenderer", new ClassFactory(myButterfly));
series1.setStyle("legendMarkerRenderer", new ClassFactory(myButterfly));
}
]]></mx:Script>
<mx:Panel title="Plot Chart">
<mx:PlotChart id="myChart"
dataProvider="{expenses}"
showDataTips="true"
>
<mx:series>
<!-- First series uses custom class renderer. -->
<mx:PlotSeries
id="series1"
xField="Expenses"
yField="Profit"
displayName="Plot 1"
radius="20"
/>
<!-- Second series uses DiamondItemRenderer. -->
<mx:PlotSeries
id="series2"
xField="Amount"
yField="Expenses"
displayName="Plot 2"
itemRenderer="mx.charts.renderers.CircleItemRenderer"
/>
<!-- Third series uses CrossItemRenderer. -->
<mx:PlotSeries
id="series3"
xField="Profit"
yField="Amount"
displayName="Plot 3"
itemRenderer="mx.charts.renderers.CrossItemRenderer"
/>
</mx:series>
</mx:PlotChart>
<mx:Legend dataProvider="{myChart}"/>
</mx:Panel>
</mx:Application>
The executing SWF file for the previous example is shown below:
Creating a custom renderer class for your chart items can give you more control than creating simple graphical renderers. Using class-based renderers is very similar to using programmatic skins, as described in Creating programmatic skins.
One approach to is to extend the ProgrammaticSkin class and implement the IDataRenderer interface. In this approach, you can provide all of the logic for drawing chart items in your custom class, and maintain the greatest control over its appearance. For example, you use methods in the Graphics class to draw and fill the rectangles of the bars in a BarChart control.
When you implement the IDataRenderer interface, you must define a setter and getter method to implement the data property. This data property is of the type of the series item. In the case of a ColumnSeries, it is a ColumnSeriesItem. Other item types include BarSeriesItem, BubbleSeriesItem, LineSeriesItem, and PlotSeriesItem.
In your class, you override the updateDisplayList() method with the logic for drawing the chart item as well as setting any custom properties. You should also call the super.updateDisplayList() method.
The following example renders the chart items and uses an Array of colors to color each column in the ColumnChart control differently:
// charts/CycleColorRenderer.as
package { // Empty package.
import mx.charts.series.items.ColumnSeriesItem;
import mx.skins.ProgrammaticSkin;
import mx.core.IDataRenderer;
import flash.display.Graphics;
public class CycleColorRenderer extends mx.skins.ProgrammaticSkin
implements IDataRenderer {
private var colors:Array = [0xCCCC99,0x999933,0x999966];
private var _chartItem:ColumnSeriesItem;
public function CycleColorRenderer() {
// Empty constructor.
}
public function get data():Object {
return _chartItem;
}
public function set data(value:Object):void {
_chartItem = value as ColumnSeriesItem;
invalidateDisplayList();
}
override protected function
updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
var g:Graphics = graphics;
g.clear();
g.beginFill(colors[(_chartItem == null)? 0:_chartItem.index]);
g.drawRect(0, 0, unscaledWidth, unscaledHeight);
g.endFill();
}
} // Close class.
} // Close package.
In your Flex application, you use this class as the renderer by using the itemRenderer property of the ColumnSeries, as the following example shows:
<?xml version="1.0"?>
<!-- charts/ProgrammaticRenderer.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
[Bindable]
public var expenses:Object = [
{Month:"Jan", Profit:2000, Expenses:1500},
{Month:"Feb", Profit:1000, Expenses:200},
{Month:"Mar", Profit:1500, Expenses:500}
];
]]>
</mx:Script>
<mx:Panel title="ColumnChart control with a programmatic ItemRenderer">
<mx:ColumnChart id="column" dataProvider="{expenses}" showDataTips="true">
<mx:horizontalAxis>
<mx:CategoryAxis
dataProvider="{expenses}"
categoryField="Month"
/>
</mx:horizontalAxis>
<mx:series>
<mx:Array>
<mx:ColumnSeries
xField="Month"
yField="Expenses"
displayName="Expenses"
itemRenderer="CycleColorRenderer"
/>
</mx:Array>
</mx:series>
</mx:ColumnChart>
</mx:Panel>
</mx:Application>
The executing SWF file for the previous example is shown below:
For more information on overriding the updateDisplayList() method, see Implementing the updateDisplayList() method.