Using multiple axes

One potential problem when using more than one data series in a single chart is that if the scales of the data are very different, the data points might be plotted in very different areas on the chart’s canvas. For example, one stock price could trade in the range of $100 to $150, while another stock price could fluctuate from $2 to $2.50. If you plot both stocks in the same chart, it would be difficult to see any correlation between the prices, even with a logarithmic axis.

To work around this problem, you can use multiple axes in your charts so that each data series is positioned relative to its own axis. All chart controls that are subclasses of CartesianChart support adding additional sets of data on a additional scales in the horizontal axis, vertical axis, or both. (This applies to all charts except the PieChart control.) You can use values on the additional axes to compare multiple sets of data that are on different scales, such as stock prices that trade in different ranges.

The following example shows a stock price that trades within a $40 to $45 range, and another stock price that trades within a $150 to $160 range. The values of the axis on the left show the range of values of the first stock, and the values of the axis on the right show the range of values of the second stock.

A chart with two series, and two axis ranges.

To use multiple axes in a chart, you first define the chart’s series and their axes. For example, for a chart that mixes columns with a line, you would have a ColumnSeries and LineSeries. For each of these, you would likely also define the vertical axis, as the following example shows:

<mx:series> 
    <mx:ColumnSeries id="cs1" dataProvider="{SMITH}" yField="close"> 
        <mx:verticalAxis> 
            <mx:LinearAxis id="v1" minimum="40" maximum="50"/> 
        </mx:verticalAxis> 
    </mx:ColumnSeries> 
    <mx:LineSeries id="cs2" dataProvider="{DECKER}" yField="close"> 
        <mx:verticalAxis> 
            <mx:LinearAxis id="v2" minimum="150" maximum="170"/> 
        </mx:verticalAxis> 
    </mx:LineSeries> 
</mx:series>

You then define the axis renderers, and bind their axis properties to the series’ axes. In this case, you define two vertical axis renderers, and bind them to the LinearAxis objects.

<mx:verticalAxisRenderers> 
    <mx:AxisRenderer placement="left" axis="{v1}"/> 
    <mx:AxisRenderer placement="left" axis="{v2}"/> 
</mx:verticalAxisRenderers>

Note that you control the location of the axis by using the placement property of the AxisRenderer. For vertical axis renderers, valid values are left and right. For horizontal axis renderers, valid values are top and bottom.

Axes can be independent of the series definition, too. For example, you can also point more than one series to the same axis. In this case, you could define a horizontal axis, as follows:

<mx:horizontalAxis> 
    <mx:CategoryAxis id="h1" categoryField="date"/> 
<mx:horizontalAxis>

And then bind it to the series, like this:

<mx:ColumnSeries id="cs1" horizontalAxis="{h1}" dataProvider="{SMITH}" yField="close"> 
... 
<mx:LineSeries id="cs2" horizontalAxis="{h1}" dataProvider="{DECKER}" yField="close">

And you can bind an axis renderer to that same axis:

<mx:horizontalAxisRenderers> 
    <mx:AxisRenderer placement="bottom" axis="{h1}"/> 
</mx:horizontalAxisRenderers>

The final result is a chart with multiple axes, but whose series share some of the same properties defined by common axis renderers.

<?xml version="1.0"?>
<!-- charts/MultipleAxes.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    creationComplete="srv_fe.send();srv_strk.send()"
    height="600">

    <fx:Declarations>
        <!-- To see data in an HTML table, go to http://aspexamples.adobe.com/chart_examples/stocks.aspx -->  

        <!-- View source of the following pages to see the structure of the data that Flex uses in this example. -->
        <mx:HTTPService id="srv_fe" url="http://aspexamples.adobe.com/chart_examples/stocks-xml.aspx?tickerSymbol=FE"/>
        <mx:HTTPService id="srv_strk" url="http://aspexamples.adobe.com/chart_examples/stocks-xml.aspx?tickerSymbol=STRK"/>
    </fx:Declarations>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Multiple Axes with Multiple Data Series" 
     width="400" height="400">
     <s:layout>
         <s:VerticalLayout/>
     </s:layout>
     <mx:ColumnChart id="myChart"
        showDataTips="true"
        height="250"
        width="350">
        <mx:horizontalAxis>
           <mx:DateTimeAxis id="h1" dataUnits="days"/>
        </mx:horizontalAxis>
        
          <mx:horizontalAxisRenderers>
            <mx:AxisRenderer placement="bottom" axis="{h1}"/>
        </mx:horizontalAxisRenderers>

        <mx:verticalAxisRenderers>
            <mx:AxisRenderer placement="left" axis="{v1}"/>
            <mx:AxisRenderer placement="right" axis="{v2}"/>
        </mx:verticalAxisRenderers>

        <mx:series>
           <mx:ColumnSeries
                dataProvider="{srv_fe.lastResult.data.result}"
                xField="date"
                yField="close"
                displayName="FE">
                  <mx:verticalAxis>
                     <mx:LinearAxis id="v1" minimum="2" maximum="5"/>
                  </mx:verticalAxis>
           </mx:ColumnSeries>
           <mx:LineSeries
                dataProvider="{srv_strk.lastResult.data.result}"
                xField="date"
                yField="close"
                displayName="STRK">
                  <mx:verticalAxis>
                     <mx:LinearAxis id="v2" minimum="40" maximum="50"/>
                  </mx:verticalAxis>
           </mx:LineSeries>
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend dataProvider="{myChart}"/>
  </s:Panel>
</s:Application>

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

Even if the verticalAxisRenderers or horizontalAxisRenderers properties have not been specified, Cartesian charts will create default horizontal and vertical axis renderers based on the default axes of the chart.

When using multiple axes, it is important to recognize that it will not necessarily be immediately apparent which axis applies to which data set in the chart. As a result, you should try to style the axes so that they match the styles of the chart items.

The following example defines two colors and then uses those colors in the axis renderers and in the strokes and fills for the chart items:

<?xml version="1.0"?>
<!-- charts/StyledMultipleAxes.mxml -->
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    creationComplete="srv_fe.send();srv_strk.send()"
    height="600">

    <fx:Script>
        <![CDATA[
            [Bindable]
            public var c1:Number = 0x224488;

            [Bindable]
            public var c2:Number = 0x884422;
        ]]>
    </fx:Script>

    <fx:Declarations>
        <!-- To see data in an HTML table, go to http://aspexamples.adobe.com/chart_examples/stocks.aspx -->  

        <!-- View source of the following pages to see the structure of the data that Flex uses in this example. -->
        <mx:HTTPService id="srv_fe" url="http://aspexamples.adobe.com/chart_examples/stocks-xml.aspx?tickerSymbol=FE"/>
        <mx:HTTPService id="srv_strk" url="http://aspexamples.adobe.com/chart_examples/stocks-xml.aspx?tickerSymbol=STRK"/>

        <mx:SolidColorStroke id="h1Stroke" color="{c1}" 
            weight="8" alpha=".75" caps="square"/>

        <mx:SolidColorStroke id="h2Stroke" 
            color="{c2}" weight="8" alpha=".75" caps="square"/>
    </fx:Declarations>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

  <s:Panel title="Multiple Axes with Multiple Data Series" 
    width="400" height="400">
     <s:layout>
         <s:VerticalLayout/>
     </s:layout>
     <mx:ColumnChart id="myChart"
        showDataTips="true"
        height="250" width="350">
        <mx:horizontalAxis>
           <mx:DateTimeAxis id="h1" dataUnits="days"/>
        </mx:horizontalAxis>
        
          <mx:horizontalAxisRenderers>
            <mx:AxisRenderer placement="bottom" axis="{h1}"/>
        </mx:horizontalAxisRenderers>

        <mx:verticalAxisRenderers>
            <mx:AxisRenderer placement="left" axis="{v1}">
                <mx:axisStroke>{h1Stroke}</mx:axisStroke>
               </mx:AxisRenderer>            
            <mx:AxisRenderer placement="right" axis="{v2}">
                <mx:axisStroke>{h2Stroke}</mx:axisStroke>            
               </mx:AxisRenderer>                        
        </mx:verticalAxisRenderers>

        <mx:series>
           <mx:ColumnSeries
                dataProvider="{srv_fe.lastResult.data.result}"
                xField="date" yField="close"
                displayName="FE">
                  <mx:verticalAxis>
                     <mx:LinearAxis id="v1" minimum="2" maximum="5"/>
                  </mx:verticalAxis>
                <mx:fill>
                    <mx:SolidColor color="{c1}"/>
                </mx:fill>
               </mx:ColumnSeries>
           <mx:LineSeries
                dataProvider="{srv_strk.lastResult.data.result}"
                xField="date" yField="close"
                displayName="STRK">
                  <mx:verticalAxis>
                     <mx:LinearAxis id="v2" minimum="40" maximum="50"/>
                  </mx:verticalAxis>
               <mx:lineStroke>
                    <mx:SolidColorStroke color="{c2}" weight="4" alpha="1"/>
                </mx:lineStroke>
               </mx:LineSeries>
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend dataProvider="{myChart}"/>
  </s:Panel>
</s:Application>

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

You can customize labels by using the labelFunction property of the AxisRenderer class. This lets you control the labels if you use multiple axes. For more information, see Customizing axis labels.

For CartesianChart controls, there is no limit to the number of axes you can have.

For PolarChart controls, such as a PieChart, you generally do not use multiple axes because even though each series could have its own angular axis, the angular axis is always from 0 to 360 (the size of the wedge).