Adobe Flex 3 Help

Using per-item fills

You can customize the appearance of chart items in a series by using the fillFunction property to define the fill. This function takes the chart item and its index as arguments, so that you can examine the chart item's data values and return a fill based on whatever criteria you choose to use.

Programmatically assigning fills lets you set a threshold for color values, or conditionalize the colors of your chart items. For example, if the size of a pie wedge is greater than 25%, make it red, or if a column's value is greater than 100, make it green.

You set the value of the fillFunction property on each series, so if you have multiple series, you can have multiple fill functions, or all series can share the same fill function.

The signature of the fillFunction is as follows:

function_name(element:ChartItem, index:Number):IFill { ... }

The following table describes the arguments:

Argument

Description

element

The chart item for which the fill is created; type ChartItem.

index

The index of the chart item in the series's data provider; type Number.

The fillFunction property returns a Fill object (an object that implements the IFill interface). This object is typically an instance of the SolidColor class, but it can also be of type BitmapFill, LinearGradient, or RadialGradient. For information on working with gradients, see Using gradient fills with chart controls.

The returned fill from a fillFunction takes precedence over fills that are set with traditional style methods. For example, if you set the value of the fill or fills property of a series and also specify a fillFunction, the fills are ignored and the fill returned by the fillFunction is used when rendering the chart items in the series.

The following example compares the value of the yField in the data provider when it fills each chart item. If the yField value (corresponding to the CurrentAmount field) is greater than $50,000, the column is green. If it is less than $50,000, the column is red.

<?xml version="1.0"?>
<!-- charts/SimpleFillFunction.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script>
    <![CDATA[

     import mx.graphics.IFill;
     import mx.graphics.SolidColor;
     import mx.collections.ArrayCollection;
     import mx.charts.ChartItem;
     import mx.charts.series.items.ColumnSeriesItem;

     [Bindable]
     public var sales:ArrayCollection = new ArrayCollection([
        { Name:"Reiner", CurrentAmount:69000 },
        { Name:"Klaus", CurrentAmount:38000 },
        { Name:"Alan", CurrentAmount:44000 },
        { Name:"Wolfgang", CurrentAmount:33000 },
        { Name:"Francis", CurrentAmount:20000 },
        { Name:"Klaus", CurrentAmount:55000 },
        { Name:"Martin", CurrentAmount:70000 },
        { Name:"Mac", CurrentAmount:35000 },
        { Name:"Friedemann", CurrentAmount:38000 },
        { Name:"Bruno", CurrentAmount:40000 }
     ]);
     
    private function myFillFunction(element:ChartItem, index:Number):IFill {
        var c:SolidColor = new SolidColor(0x00CC00);

        var item:ColumnSeriesItem = ColumnSeriesItem(element);
        var sales:Number = Number(item.yValue);       

        if (sales >= 50000) {
            return c;
        } else {
            // They have not met their goal.
            c.color = 0xFF0000;
        }
        return c;
    }
    
    ]]>
  </mx:Script>

  <mx:Panel title="Using a custom fillFunction in a Column Chart">
     <mx:ColumnChart id="myChart" 
        dataProvider="{sales}" 
        showDataTips="true"
     >
        <mx:horizontalAxis>
           <mx:CategoryAxis 
                title="Sales Person"
                categoryField="Name"
           />
        </mx:horizontalAxis>
        <mx:verticalAxis>
            <mx:LinearAxis title="Sales (in $USD)"/>
        </mx:verticalAxis>
        
        <mx:series>
           <mx:ColumnSeries id="currSalesSeries" 
                xField="Name" 
                yField="CurrentAmount" 
                fillFunction="myFillFunction" 
                displayName="Current Sales"
           />
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend>
        <mx:LegendItem label="More than $50K" fontWeight="bold">
           <mx:fill>
            <mx:SolidColor color="0x00FF00"/>
           </mx:fill>
           <mx:stroke>
            <mx:Stroke color="0x000000" weight="1"/>
           </mx:stroke>
        </mx:LegendItem>
        <mx:LegendItem label="Less than $50K" fontWeight="bold">
           <mx:fill>
            <mx:SolidColor color="0xFF0000"/>
           </mx:fill>
           <mx:stroke>
            <mx:Stroke color="0x000000" weight="1"/>
           </mx:stroke>
         </mx:LegendItem>
     </mx:Legend>
  </mx:Panel>
</mx:Application>

The executing SWF file for the previous example is shown below:

This example defines custom entries in the Legend. If you use the fillFunction property to define the fills of chart items, and you want a Legend control in your chart, you must manually create the Legend object and its LegendItem objects. For more information on creating Legend and LegendItem objects, see Using Legend controls.

By using the index argument that is passed to the fill function, you can also access other items inside the same series.

The following example sets the color of the fill to green for only the columns whose item value is greater than the previous item's value. Otherwise, it sets the color of the fill to red.

<?xml version="1.0"?>
<!-- charts/ComparativeFillFunction.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script>
    <![CDATA[

     import mx.graphics.IFill;
     import mx.graphics.SolidColor;
     import mx.collections.ArrayCollection;
     import mx.charts.ChartItem;
     import mx.charts.series.items.ColumnSeriesItem;

     [Bindable]
     public var sales:ArrayCollection = new ArrayCollection([
        { Name:"Reiner", CurrentAmount:69000 },
        { Name:"Klaus", CurrentAmount:38000 },
        { Name:"Alan", CurrentAmount:44000 },
        { Name:"Wolfgang", CurrentAmount:33000 },
        { Name:"Francis", CurrentAmount:20000 },
        { Name:"Klaus", CurrentAmount:55000 },
        { Name:"Martin", CurrentAmount:70000 },
        { Name:"Mac", CurrentAmount:35000 },
        { Name:"Friedemann", CurrentAmount:38000 },
        { Name:"Bruno", CurrentAmount:40000 }
     ]);
     
    private function myFillFunction(element:ChartItem, index:Number):IFill {
        // Default to green.
        var c:SolidColor = new SolidColor(0x00FF00);

        var item:ColumnSeriesItem = ColumnSeriesItem(element);
        var sales:Number = Number(item.yValue);       

        if (index == 0) {
            // The first column should be green, no matter the value.
            return c;        
        } else {
            var prevVal:Number = 
                Number(currSalesSeries.items[index - 1].yValue);  
            var curVal:Number = 
                Number(currSalesSeries.items[index].yValue);
            var diff:Number = curVal - prevVal;

            if (diff >= 0) {
                // Current column's value is greater than the previous.
                return c;
            } else {
                // Previous column's value is greater than the current.
                c.color = 0xFF0000;
            }
        }
        return c;
    }
    
    ]]>
  </mx:Script>

  <mx:Panel title="Using a custom fillFunction in a Column Chart">
     <mx:ColumnChart id="myChart" 
        dataProvider="{sales}" 
        showDataTips="true"
     >
        <mx:horizontalAxis>
           <mx:CategoryAxis 
                title="Sales Person"
                categoryField="Name"
           />
        </mx:horizontalAxis>
        <mx:verticalAxis>
            <mx:LinearAxis title="Sales (in $USD)"/>
        </mx:verticalAxis>
        
        <mx:series>
           <mx:ColumnSeries id="currSalesSeries" 
                xField="Name" 
                yField="CurrentAmount" 
                fillFunction="myFillFunction" 
                displayName="Current Sales"
           />
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend>
        <mx:LegendItem label="More than Previous" fontWeight="bold">
           <mx:fill>
            <mx:SolidColor color="0x00FF00"/>
           </mx:fill>
           <mx:stroke>
            <mx:Stroke color="0x000000" weight="1"/>
           </mx:stroke>
        </mx:LegendItem>
        <mx:LegendItem label="Less than Previous" fontWeight="bold">
           <mx:fill>
            <mx:SolidColor color="0xFF0000"/>
           </mx:fill>
           <mx:stroke>
            <mx:Stroke color="0x000000" weight="1"/>
           </mx:stroke>
         </mx:LegendItem>
     </mx:Legend>
  </mx:Panel>
</mx:Application>

The executing SWF file for the previous example is shown below:

This example defines custom entries in the Legend because using a fillFunction prevents you from using an automatically generated Legend. For more information on creating Legend objects, see Using Legend controls.

You can also access other series data inside a fill function so that you can perform comparisons against other series in a data provider. While you cannot reference a series from inside the fill function by using the fill function's arguments, you can use the id property of a series to gain access to its data.

The following example uses chart items in more than one series to determine what color the fill for each chart item should be. In this case, it compares the value of the current amount of sales in the currentSalesSeries series against the sales goal in the salesGoalSeries series. If the goal is met, the positive difference between the goal and the actual sales is green. If the goal is not yet met, the negative difference between the goal and the actual sales is red.

<?xml version="1.0"?>
<!-- charts/ComplexFillFunction.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script>
    <![CDATA[

     import mx.graphics.IFill;
     import mx.graphics.SolidColor;
     import mx.collections.ArrayCollection;
     import mx.charts.ChartItem;
     import mx.charts.series.items.ColumnSeriesItem;

     [Bindable]
     public var sales:ArrayCollection = new ArrayCollection([
        { Name:"Reiner", SalesGoal:65000, CurrentAmount:69000 },
        { Name:"Klaus", SalesGoal:40000, CurrentAmount:38000 },
        { Name:"Alan", SalesGoal:40000, CurrentAmount:44000 },
        { Name:"Wolfgang", SalesGoal:48000, CurrentAmount:33000 },
        { Name:"Francis", SalesGoal:22000, CurrentAmount:20000 },
        { Name:"Klaus", SalesGoal:50000, CurrentAmount:55000 },
        { Name:"Martin", SalesGoal:44000, CurrentAmount:70000 },
        { Name:"Mac", SalesGoal:40000, CurrentAmount:35000 },
        { Name:"Friedemann", SalesGoal:38000, CurrentAmount:38000 },
        { Name:"Bruno", SalesGoal:42000, CurrentAmount:40000 }
     ]);
     
    private function myFillFunction(element:ChartItem, index:Number):IFill {
        var item:ColumnSeriesItem = ColumnSeriesItem(element);

        trace("--------------------------------------------------");        
        trace("Item index: " + index);        
        trace("Sales Person: " + item.xValue);
        trace("Current Amount: " + currSalesSeries.items[index].yValue);
        trace("Sales Goal: " + item.yValue);
        
        // Set default color and alpha.
        var c:SolidColor = new SolidColor(0x00CC00);
        
        /* Use the yNumber properties rather than the yValue properties
           because the conversion to a Number is already done for 
           you. As a result, you do not have to cast them to a Number,
           which would be less efficient. */
        var goal:Number = item.yNumber;
        var currentAmount:Number = currSalesSeries.items[index].yNumber;
        
        // Determine if the goal was met or not.
        var diff:Number = currentAmount - goal;      
        
        if (diff >= 0) {
            // Sales person met their goal.
            return c; 
        } else if (diff < 0) {
            // Sales person did not meet their goal.
            c.color = 0xFF0000;
            c.alpha = .2;
        }
        return c;
    }
    
    ]]>
  </mx:Script>

  <mx:Panel title="Using a custom fillFunction in a Column Chart">
     <mx:ColumnChart id="myChart" 
        dataProvider="{sales}" 
        type="overlaid" 
        showDataTips="true"
     >
        <mx:horizontalAxis>
           <mx:CategoryAxis 
                title="Sales Person"
                categoryField="Name"
           />
        </mx:horizontalAxis>
        <mx:verticalAxis>
            <mx:LinearAxis title="Sales (in $USD)"/>
        </mx:verticalAxis>
        
        <mx:series>
           <mx:ColumnSeries id="currSalesSeries" 
                xField="Name" 
                yField="CurrentAmount" 
                displayName="Current Sales"
            >
                <mx:fill>
                    <mx:SolidColor color="0x00FF00"/>
                </mx:fill>
           </mx:ColumnSeries>
           <mx:ColumnSeries id="salesGoalSeries" 
                xField="Name" 
                yField="SalesGoal" 
                fillFunction="myFillFunction" 
                displayName="Sales Goal"
           >
           </mx:ColumnSeries>
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend>
        <mx:LegendItem label="Goal" fontWeight="bold">
           <mx:fill>
            <mx:SolidColor color="0x00CC00"/>
           </mx:fill>
           <mx:stroke>
            <mx:Stroke color="0x000000" weight="1"/>
           </mx:stroke>
        </mx:LegendItem>
        <mx:LegendItem label="Exceeded Goal" fontWeight="bold">
           <mx:fill>
            <mx:SolidColor color="0x00FF00"/>
           </mx:fill>
           <mx:stroke>
            <mx:Stroke color="0x000000" weight="1"/>
           </mx:stroke>
         </mx:LegendItem>
        <mx:LegendItem label="Missed Goal" fontWeight="bold">
           <mx:fill>
            <mx:SolidColor color="0xFF0000" alpha=".2"/>
           </mx:fill>
           <mx:stroke>
            <mx:Stroke color="0x000000" weight="1"/>
           </mx:stroke>
         </mx:LegendItem>
     </mx:Legend>
  </mx:Panel>
</mx:Application>

The executing SWF file for the previous example is shown below:

This chart uses overlaid columns, and sets the value of the top-most column's alpha property to .2 if it the sales goal was not met. By using an alpha property, you can view the column underneath the current column. This lets you show the difference for only the items that have missed sales goals without drawing stacked columns.