Apache Adobe Flex TutorialTutoriaux Adobe Flex & AIR en Français

2juil/094

Flex Chart – Utiliser une dataFunction pour les structures de données complexes

Dans la plupart des cas, la data utilisée comme dataProvider d'un chart est assez plate. Par exemple, des objets contenant une seule série de champs:

{month: "Aug", close: 45.87, open:25.19}

Ou un XML contenant simplement un seul niveau de nœuds enfants dans une structure à plat:

<stock>
	<month>Aug</month>
	<close>45.87</close>
	<open>25.19</open>
</stock>

Dans ces cas-là, vous assignez les champs du dataProvider aux items dans le Chart en utilisant les propriétés xField et yField pour les series, ou le categoryField pour les axes, comme par exemple:

<mx:ColumnSeries yField="close"/>
<mx:CategoryAxis categoryField="month"/>

Cependant, la structure de donnée de votre chart peut être faîtes d'objets plus complexes, comme des objets à l'intérieur d'objets ou un XML avec plusieurs niveaux d'enfants. Par exemple, vous pourriez avoir des Object à l'intérieur d'un Object:

{month: "Aug", close: {High:45.87,Low:12.2}, open:25.19}

Ou utiliser des tags nested dans un objet XML:

<stock>
	<date>
		<month>Aug</month>
	</date>
	<price>
		<close>45.87</close>
		<open>25.19</open>
	</price>
</stock>

Dans ces cas-là, vous ne pouvez pas faire référence à la data en utilisant une notation à plat comme yField="close". Vous ne pouvez pas non plus utilisant la notation point "dot notation". Par exemple, yField="values.close" ou categoryField="data.month" ne sont pas valides.

A la place, vous devez utiliser une méthode dataFunction pour définir quel champ de ChartItem sera peuplé par le dataProvider.

Pour la classe CategoryAxis, la dataFunction a la signature suivante:

function_name(axis:AxisBase, item:Object):Object

Où axis est la classe de base pour l'axe courant, et item est l'item du dataProvider.

Pour une classe Series, la dataFunction a la signature suivante:

function_name(series:Series, item:Object, fieldName:String):Object

Où series est une référence vers la series courante, item est l'item du dataProvider, et fieldName est le champ dans le ChartItem courant qui va être peuplé.

L'exemple suivant crée deux fonctions qui vont accéder à une donnée complexe à la fois pour les axes que pour les series:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%">
	<mx:Script><![CDATA[
		import mx.charts.chartClasses.AxisBase;
		import mx.charts.chartClasses.Series;
		import mx.charts.CategoryAxis;
		import mx.charts.chartClasses.IAxis;
		import mx.charts.chartClasses.ChartBase;
		import mx.charts.chartClasses.CartesianTransform;
		// This data provider contains complex, nested objects.
		[Bindable]
		public var SMITH:Array = [
			{month: "Aug", close: {High:45.87,Low:12.2}, open:25.19},
			{month: "Sep", close: {High:45.74,Low:10.23}, open:35.29},
			{month: "Oct", close: {High:45.77,Low:12.13}, open:45.19},
			{month: "Nov", close: {High:46.06,Low:10.45}, open:15.59},
		];
		private function dataFunc(series:Series, item:Object, fieldName:String):Object {
			trace("fieldName: " + fieldName);
			if(fieldName == "yValue" && series.id=="highClose"){
				return(item.close.High);
			}
			else if(fieldName == "yValue" && series.id=="lowClose"){
				return(item.close.Low);
			}
			else if(fieldName == "xValue"){
				return(item.month);
			}
			else{
				return null;
			}
		}
		private function catFunc(axis:AxisBase, item:Object):Object {
			for (var s:String in item) {
				trace(s + ":" + item[s]);
			}
			return(item.month);
		}
	]]></mx:Script>
	<mx:ColumnChart id="chart"
		dataProvider="{SMITH}"
		showDataTips="true"
		width="100%"
		height="100%"
		>
		<mx:horizontalAxis>
			<!-- The dataFunction replaces "categoryField='month'. -->
			<mx:CategoryAxis id="h1" dataFunction="catFunc"/>
		</mx:horizontalAxis>
		<mx:series>
			<!-- The dataFunction replaces yField value, which cannot drill
			down into an object (close.High is not valid). -->
			<mx:ColumnSeries id="highClose"
				displayName="Close (High)"
				dataFunction="dataFunc"
			/>
			<!-- The dataFunction replaces yField value, which cannot drill
			down into an object (close.Low is not valid). -->
			<mx:ColumnSeries id="lowClose"
				displayName="Close (Low)"
				dataFunction="dataFunc"
			/>
		</mx:series>
	</mx:ColumnChart>
</mx:Application>

Flex Source Code Download: Télécharger le code source complet de l'application

This movie requires Flash Player 11

Articles similaires

Commentaires (4) Trackbacks (0)
  1. Bonjour,

    J'ai un petit problème :

    J'ai 2 LineSeries à afficher dans un LineChart, et je veux donc afficher 2 courbes, à partir des valeurs provenant d'un fichier XML, mais sur lesquelles j'effectue des opérations préalablement.
    Donc je crée ma propre dataFunction qui effectue les traitements sur les données.
    Ensuite je l'assigne à mes lineSeries :
    myLocalSeries1.dataFunction=myDataFunction;
    myLocalSeries2.dataFunction=myDataFunction;
    Seulement à l'exécution rien ne s'affiche dans le graphe, pourtant quand je trace ce que renvoie myDataFunction, tout va bien elle se déclenche et renvoie bien les bonnes données.

    Des idées ?

    Merci beaucoup

    AnSo

  2. Un peu de code peut etre ? ici si tu veux ou par email (voir en bas de la page)

    Fabien

  3. (je recommence avec les balises, ce sera peut-être plus lisible)

    Voilà une partie de mon code :

    Actionscript:
    1. // ma dataFunction :
    2. // j'ai 2 courbes : ptfSeries et indexSeries, que je veux transformer en base 100
    3. private function transformToBase100 (series:LineSeries, item:Object, fieldName:String):Object {
    4.    if(fieldName == "xValue") {
    5.       trace("[xValue] "+item.date);
    6.       return(item.date);
    7.    } else
    8.       if(fieldName == "yValue" &amp;&amp; series.id == "ptfSeries" &amp;&amp; firstValuePtf!=0) {
    9.          trace("[yValue][ptfSeries] "+(Number(item.valo))/firstValuePtf);
    10.          return (Number(item))/firstValuePtf;
    11.       } else
    12.          if(fieldName == "yValue" &amp;&amp; series.id == "indexSeries" &amp;&amp; firstValueIndex!=0) {
    13.             trace("[yValue][indexSeries] "+(Number(item.valo))/firstValueIndex);
    14.             return (Number(item))/firstValueIndex;
    15.          } else {
    16.             return null;
    17.          }
    18. }
    19.  
    20. // la fonction qui crée le graphe : (je dispose de 2 objets XML contenant les données des 2 courbes : XMLDatasPtfFile et XMLDatasIndexFile)
    21. private function makeGraph():void {
    22.  
    23.    var vAxis:LinearAxis = new LinearAxis();
    24.    var hAxis:DateTimeAxis = new DateTimeAxis();
    25.    var localSeriesPtf:LineSeries = new LineSeries();
    26.    var localSeriesIndex:LineSeries = new LineSeries();
    27.  
    28.    // LINE OF PTF VALORIZATION
    29.    localSeriesPtf.id = "ptfSeries";
    30.    localSeriesPtf.displayName = "portfolio";
    31.    localSeriesPtf.dataProvider = XMLDatasPtfFile.item;
    32.    localSeriesPtf.dataFunction = transformToBase100;
    33.  
    34.    // lineSeries allocation to chart
    35.    var mySeries:Array=new Array();
    36.    mySeries.push(localSeriesPtf);
    37.  
    38.    // LINE OF INDEX VALORIZATION
    39.    localSeriesIndex.id = "indexSeries";
    40.    localSeriesIndex.displayName = "index "+XMLDatasIndexFile.instrumentName;
    41.    localSeriesIndex.dataProvider = XMLDatasIndexFile.item;
    42.    localSeriesIndex.dataFunction = transformToBase100;
    43.  
    44.    // lineSeries allocation to chart
    45.    mySeries.push(localSeriesIndex);
    46.  
    47.    myChart.series = mySeries;
    48.  
    49.    // vertical axis
    50.    vAxis.title="valorization";
    51.  
    52.    // horizontal axis
    53.    hAxis.dataUnits = "date";
    54.    hAxis.title="date";
    55.    hAxis.parseFunction = createDate;
    56.  
    57.    // labels of dates formatting
    58.    hAxis.labelFunction = defineDateLabel;
    59.    myChart.horizontalAxis = hAxis;
    60.    myChart.verticalAxis = vAxis;
    61. }

    Donc les courbes ne s'affichent pas, pourtant les traces de la dataFunction sont les bonnes.

    Merci !!

  4. J'ai trouvé la solution : mon code est bon, il s'agissait d'un problème dans le fichier de données XML, qui était mal formé.


Leave a comment

(required)

Aucun trackbacks pour l'instant