Adobe Flex 3 Help

Using the HitData object

Flex dispatches a ChartItemEvent object for each chart data event such as when you click on an item in the series. In addition to the standard target and type properties that all Event objects have, Flex adds the hitData property to the ChartItemEvent object. This property is an object instance of the HitData class. The hitData property contains information about the data point that is closest to the mouse pointer at the time of the mouse event.

The item property of the HitData object refers to the data point. You can use that property to access its value by its name, as the previous example shows. The HitData x and y properties refer to the screen coordinates of the data point.

Only data points within the radius determined by the mouseSensitivity property can trigger an event on that data point. For more information, see Changing mouse sensitivity.

The following example uses the itemDoubleClick event handler to display HitData information for data points in a column chart when the user clicks on a column. Because each column in the ColumnChart control is associated with a single data point value, clicking the mouse anywhere in the column displays the same information.

<?xml version="1.0"?>
<!-- charts/HitDataOnClick.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize=
"init()">
  <mx:Script><![CDATA[
     import mx.charts.events.ChartItemEvent;
     import mx.collections.ArrayCollection;
     [Bindable]
     public var dataSet:ArrayCollection = new ArrayCollection([
        {Month:"Jan", Expenses:1500},
        {Month:"Feb", Expenses:200},
        {Month:"Mar", Expenses:500}
     ]);
     // Define the event handler.
     public function myListener(e:ChartItemEvent):void {
        ti1.text = e.hitData.item.Expenses;
        ti2.text = e.hitData.x + "/" + e.hitData.y;
     }

     // Define event listeners when the application initializes.
     public function init():void {
        myChart.addEventListener(ChartItemEvent.ITEM_DOUBLE_CLICK, myListener);
     }
  ]]></mx:Script>
  <mx:Panel title="Accessing HitData Object in Event Handlers">
     <mx:ColumnChart id="myChart" 
        dataProvider="{dataSet}" 
        doubleClickEnabled="true"
        showDataTips="true"
     >
        <mx:horizontalAxis>
           <mx:CategoryAxis categoryField="Month"/>
        </mx:horizontalAxis>
        <mx:series>
           <mx:ColumnSeries yField="Expenses"/>
        </mx:series>
     </mx:ColumnChart>
     <mx:Form>
        <!--Define a form to display the event information.-->
        <mx:FormItem label="Expenses:">
           <mx:TextInput id="ti1"/>
        </mx:FormItem>
        <mx:FormItem label="x/y:">
           <mx:TextInput id="ti2"/>
        </mx:FormItem>
     </mx:Form>
     <mx:Legend dataProvider="{myChart}"/>
  </mx:Panel>
</mx:Application>

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

Getting chart elements

The HitData object accesses the chart's ChartItem objects. These objects represent data points on the screen. In addition to providing access to the data of data points, ChartItem objects provide information about the size and position of graphical elements that make up the chart. For example, you can get the x and y positions of columns in a ColumnChart.

The following example uses a semitransparent Canvas container to highlight the data point that the user clicks on with the mouse. The application also accesses the ChartItem object to get the current value to display in a ToolTip on that Canvas:

<?xml version="1.0"?>
<!-- charts/ChartItemObjectAccess.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="init()">

  <mx:Style>
     ToolTip {
        fontSize:24;
     }
     ColumnChart {
        gutterLeft: 54;
     }
  </mx:Style>

  <mx:Script><![CDATA[
     import mx.core.IFlexDisplayObject;
     import mx.charts.events.ChartItemEvent;
     import mx.charts.series.items.ColumnSeriesItem;
     import mx.charts.series.ColumnSeries;
     import mx.effects.Move;
     import mx.charts.HitData;
     import mx.collections.ArrayCollection;

     public var m:mx.effects.Move;
     public var hitData:mx.charts.HitData;
     public var chartItem:ColumnSeriesItem;
     public var renderer:IFlexDisplayObject;
     public var series:ColumnSeries;

     public var chartItemPoint:Point;
     public var highlightBoxPoint:Point;
     public var leftAdjust:Number;

     private function init():void {
        m = new Move(highlightBox);

        /* This is used to adjust the x location of
           highlightBox to account for the left gutter width. */
        leftAdjust = myChart.getStyle("gutterLeft") - 14;
     }

     [Bindable]
     private var dataSet:ArrayCollection = new ArrayCollection([
        {month:"Jan", income:12300, expense:3210},
        {month:"Feb", income:12450, expense:3100},
        {month:"Mar", income:13340, expense:3550},
        {month:"Apr", income:13489, expense:3560},
        {month:"May", income:11020, expense:4600},
        {month:"Jun", income:14030, expense:3410},
        {month:"Jul", income:15600, expense:4485},
        {month:"Aug", income:17230, expense:3892},
        {month:"Sep", income:15212, expense:3562},
        {month:"Oct", income:14980, expense:5603},
        {month:"Nov", income:15020, expense:4102},
        {month:"Dec", income:15923, expense:4789}]);

     private function overData(event:ChartItemEvent):void {

        hitData = event.hitData;
        chartItem = ColumnSeriesItem(hitData.chartItem);
        renderer = chartItem.itemRenderer;
        series = ColumnSeries(hitData.element);

        /* Add 10 pixels to give it horizontal overlap. */
        highlightBox.width = renderer.width * 2 + 10;

        /* Add 20 pixels to give it vertical overlap. */
        highlightBox.height = renderer.height + 20;

        highlightBoxPoint = new Point(highlightBox.x,
            highlightBox.y);

        /* Convert the ChartItem's pixel values from local 
           (relative to the component) to global (relative 
           to the stage). This enables you to place the Canvas 
           container using the x and y values of the stage. */
        chartItemPoint = myChart.localToGlobal(new 
            Point(chartItem.x, chartItem.y));

        /* Define the parameters of the move effect and play the effect. */
        m.xTo = chartItemPoint.x + leftAdjust;
        m.yTo = chartItemPoint.y;
        m.duration = 500;
        m.play();

        highlightBox.toolTip = "$" + chartItem.yValue.toString();
     }

  ]]></mx:Script>

  <mx:Panel id="p1">
     <mx:ColumnChart id="myChart" 
        dataProvider="{dataSet}" 
        itemClick="overData(event)" 
        mouseSensitivity="0"
     >
        <mx:horizontalAxis>
           <mx:CategoryAxis categoryField="month"/>
        </mx:horizontalAxis>
        <mx:series>
           <mx:ColumnSeries 
                displayName="Expense" 
                yField="expense"
           />
           <mx:ColumnSeries 
                displayName="Income"  
                yField="income"
           />
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend dataProvider="{myChart}"/>
  </mx:Panel>

  <!-- Define the canvas control that will be used as a highlight. -->
  <mx:Canvas id="highlightBox" 
        y="0" x="0" 
        backgroundColor="0xFFFF00"
        alpha=".5"
  />
</mx:Application>

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

For information about changing the appearance of ChartItem objects, see Skinning ChartItem objects.

Getting data with coordinates

When you create charts, you can use the coordinates on the screen to get the nearest data point or data points, or conversely, to pass the data point and get the coordinates.

The findDataPoints() and localToData() methods take coordinates and return data. The findDataPoints() method returns a HitData object. For more information, see Using the findDataPoints() method. The localToData() method returns an Array of the data. For more information, see Using the localToData() method.

You can also pass the data itself and get the coordinates with the dataToLocal() method. For more information, see Using the dataToLocal() method.

Using the findDataPoints() method

You can use the chart control's findDataPoints() method to get an Array of HitData objects by passing in x and y coordinates. If the coordinates do not correspond to the location of a data point, the findDataPoints() method returns null. Otherwise, the findDataPoints() method returns an Array of HitData objects.

The findDataPoints() method has the following signature:

findDataPoints(x:Number, y:Number):Array

The following example creates a PlotChart control and records the location of the mouse pointer as the user moves the mouse over the chart. It uses the findDataPoints() method to get an Array of HitData objects, and then displays some of the first object's properties.

<?xml version="1.0"?>
<!-- charts/FindDataPoints.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
  <mx:Script><![CDATA[
     import mx.charts.HitData;
     import mx.collections.ArrayCollection;

     [Bindable]
     public var expenses:ArrayCollection = new ArrayCollection([
        {Month:"January", Profit:2000, Expenses:1500},
        {Month:"February", Profit:1000, Expenses:200},
        {Month:"March", Profit:1500, Expenses:500},
        {Month:"April", Profit:500, Expenses:300},
        {Month:"May", Profit:1000, Expenses:450},
        {Month:"June", Profit:2000, Expenses:500}]);

     public function handleMouseMove(e:MouseEvent):void {
        // Use coordinates to get HitData object of 
        // current data point.
        var hda:Array = 
            chart.findDataPoints(e.currentTarget.mouseX, 
            e.currentTarget.mouseY);
        if (hda[0]) {
           ta.text = "Found data point " + 
                hda[0].chartItem.index + " (x/y):" + 
                Math.round(hda[0].x) + "," + 
                Math.round(hda[0].y) + "\n";
           ta.text += "Expenses:" + hda[0].item.Expenses;
        } else {
           ta.text = "No data point found  (x/y):" +
                Math.round(e.currentTarget.mouseX) + 
                "/" + Math.round(e.currentTarget.mouseY);
        }
     }
  ]]></mx:Script>
  <mx:Panel title="Plot Chart">
     <mx:PlotChart id="chart" 
        mouseMove="handleMouseMove(event)"
        dataProvider="{expenses}" 
        showDataTips="true"
        mouseSensitivity="5"
     >
        <mx:series>
           <mx:PlotSeries 
                xField="Profit" 
                yField="Expenses"
           />
        </mx:series>
     </mx:PlotChart>
  </mx:Panel>
  <mx:TextArea id="ta" width="300" height="50"/>
</mx:Application>

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

Using the localToData() method

The localToData() method takes a Point object that represents the x and y coordinates you want to get the data for and returns an Array of data values, regardless of whether any data items are at or near that point.

The following example creates a Point object from the mouse pointer's location on the screen and displays the data values associated with that point:

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

     public var p:Point;

     [Bindable]
     public var expenses:ArrayCollection = new ArrayCollection([
        {Month:"Jan", Profit:2000, Expenses:1500},
        {Month:"Feb", Profit:1000, Expenses:200},
        {Month:"Mar", Profit:1500, Expenses:500}
     ]);

     private function updateDetails(e:MouseEvent):void {
        p = new Point(myChart.mouseX,myChart.mouseY);
        mpos.text = "(" + p.x + "," + p.y + ")";

        var d:Array = myChart.localToData(p);
        dval.text = "(" + d[0] + "," + Math.floor(d[1]) + ")";

        p = myChart.dataToLocal(d[0],d[1]);
        dpos.text ="(" + Math.floor(p.x) + "," + 
            Math.floor(p.y) + ")";
     }


  ]]></mx:Script>
  <mx:Panel title="Column Chart">
     <mx:ColumnChart id="myChart" 
        dataProvider="{expenses}" 
        mouseMove="updateDetails(event)"
        showDataTips="true"
     >
        <mx:horizontalAxis>
           <mx:CategoryAxis 
                dataProvider="{expenses}" 
                categoryField="Month"
           />
        </mx:horizontalAxis>
        <mx:series>
           <mx:ColumnSeries 
                xField="Month" 
                yField="Profit"
                displayName="Profit"
           />
           <mx:ColumnSeries 
                xField="Month" 
                yField="Expenses"
                displayName="Expenses"
           />
        </mx:series>
     </mx:ColumnChart>
     <mx:Legend dataProvider="{myChart}"/>
  </mx:Panel>


  <mx:Form width="300">
     <mx:FormItem label="Mouse Position:">
        <mx:Label id="mpos"/>
     </mx:FormItem>
     <mx:FormItem label="Data Position:">
        <mx:Label id="dpos"/>
     </mx:FormItem>
     <mx:FormItem label="DATA:">
        <mx:Label id="dval"/>
     </mx:FormItem>
  </mx:Form>

</mx:Application>

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

Individual chart types determine how coordinates are mapped, and how many values are returned in the Array. The values returned are typically numeric values.

In a chart that is based on the CartesianChart class (for example, a BarChart or ColumnChart control), the first item in the returned Array is the value of the x-coordinate along the horizontal axis, and the second item is the value of the y-coordinate along the vertical axis.

In a chart based on the PolarChart class (such as PieChart), the returned Array maps the coordinates to a set of polar coordinates--an angle around the center of the chart, and a distance from the center. Those values are mapped to data values that use the first (angular) and second (radial) axes of the chart.

Using the dataToLocal() method

The dataToLocal() method converts a set of values to x and y coordinates on the screen. The values you give the method are in the "data space" of the chart; this method converts these values to coordinates. The data space is the collection of all possible combinations of data values that a chart can represent.

The number and meaning of arguments passed to the dataToLocal() method depend on the chart type. For CartesianChart controls, such as the BarChart and ColumnChart controls, the first value is used to map along the x axis, and the second value is used to map along the y axis.

For PolarChart controls, such as the PieChart control, the first value maps to the angle around the center of the chart, and the second value maps to the distance from the center of the chart along the radius.

The coordinates returned are based on 0,0 being the upper-left corner of the chart. For a ColumnChart control, for example, the height of the column is inversely related to the x coordinate that is returned.