利用AxisRenderer格式化图表刻度标签

原创文章,转载请注明出处:http://montage.iteye.com/blog/508749
用Flex做企业应用时经常要用到Flex的图表组件;Flex的图表组件非常强大,但是Flex Chart没有对图表刻度轴格式化的功能;如果10000000(一千万),这种天文数字看上去一点也不直观;
我所做的“格式化图表刻度标签”功能正是弥补了Flex Chart这一不足之处;
目前的版本支持前缀,后缀,千位符,小数保留位数,缩写;
我继承了Flex Chart的AxisRenderer命名为AxisRendererPlus,AxisRenderer是Flex Chart默认的轴渲染器。AxisRendererPlus提供了5个接口,在属性发生改变的时候通过调用invalidateProperties()使属性失效来重新触发labelFunction,在defaultLabelFunction里面做所有对标签转换的处理过程;
AxisRendererPlus.as
package com.montage.charts
{
import mx.charts.AxisRenderer;
import mx.charts.LinearAxis;
import mx.charts.chartClasses.IAxisRenderer;
import mx.formatters.NumberFormatter;

/**
* 增加的AxisRenderer支持数据格式化,前缀,后缀,千位符,小数位数;
* @author Montage
*/
public class AxisRendererPlus extends AxisRenderer
{

private var numberFmt:NumberFormatter;

/**
* 是否使用千位符
*/
private var _useThousandsSeparator:Boolean;

/**
* 保留小数位数
*/
private var _precision:int = 0;

/**
* 前缀
*/
private var _prefix:String;

/**
* 后缀
*/
private var _suffix:String;

/**
* 格式化单位
* 比如:"10000"可以转化为"10千";
*/
private var _formatUnit:FormatUnit

public function AxisRendererPlus()
{
super();
numberFmt = new NumberFormatter();
labelFunction = defaultLabelFun;
}


public function set useThousandsSeparator( value:Boolean ):void
{
_useThousandsSeparator = value;
invalidateProperties();
}
public function get useThousandsSeparator():Boolean
{
return _useThousandsSeparator;
}

public function set precision( value:int ):void
{
_precision = value;
invalidateProperties();
}
public function get precision():int
{
return _precision;
}

public function set prefix( value:String ):void
{
_prefix = value;
invalidateProperties();
}
public function get prefix():String
{
return _prefix;
}

public function set suffix( value:String ):void
{
_suffix = value;
invalidateProperties();
}
public function get suffix():String
{
return _suffix;
}

public function set formatUnit( value:FormatUnit ):void
{
_formatUnit = value;
invalidateProperties();
}
public function get formatUnit():FormatUnit
{
return _formatUnit;
}

protected function defaultLabelFun(axisRenderer:IAxisRenderer, label:String):String
{
if( axisRenderer.axis is LinearAxis )
{
var num:Number = Number( label );
if( formatUnit )
num = FormatUnit.formatByUnit(formatUnit.unit, num);

numberFmt.precision = precision;
numberFmt.useThousandsSeparator = useThousandsSeparator;
label = numberFmt.format(num);
if( prefix )
label = prefix+label;
if( formatUnit && formatUnit.unit != FormatUnit.NONE )
label += formatUnit.label;
if( suffix )
label += suffix;
}
return label;
}

}
}

FormatUnit是控件缩写功能的枚举类,比如[100000]缩写为[10]万只需要实例化一个FormatUnit对象, 所以将其实label设置为"万", unit设置为FormatUnit.TEN_THOUSAND;然后再把这个实例赋值给AxisRendererPlus.formatUnit属性就可以了;
FormatUnit.as
package com.montage.charts
{

/**
* 标签格式化单位
* @author Montage
*/
public class FormatUnit
{
public static const NONE:String = "none";
public static const HUNDRED:String = "hundred";
public static const THOUSAND:String = "thousand";
public static const TEN_THOUSAND:String = "tenThousand";
public static const LAKH:String = "lakh";
public static const MILLION:String = "million";

public function FormatUnit( label:String = null, unit:String = null )
{
_label = label;
_unit = unit;
}

private var _label:String;
private var _unit:String;

public function set label( value:String ):void
{
_label = value;
}
public function get label():String
{
return _label;
}

public function set unit( value:String ):void
{
_unit = value;
}
public function get unit():String
{
return _unit;
}

public static function formatByUnit( unitStr:String, num:Number ):Number
{
switch( unitStr )
{
case NONE :
break;

case HUNDRED :
num /= 100;
break;

case THOUSAND :
num /= 1000;
break;

case TEN_THOUSAND :
num /= 10000;
break;

case LAKH :
num /= 100000;
break;

case MILLION :
num /= 1000000;
break;

default : break;
}
return num;
}

}
}


测试页面AxisRendererDemo.mxml,我用ColumnChart来测试,由于格式化只能处理标签为数字的刻度轴,所以我在verticalAxisRenderers里面加入了一个AxisRendererPlus;
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo" minWidth="1024" minHeight="768" fontSize="12"
xmlns:charts="com.montage.charts.*">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;

[Bindable]
private var medalsAC:ArrayCollection = new ArrayCollection( [
{ Country: "USA", Gold: 35000, Silver:39000, Bronze: 29000 },
{ Country: "China", Gold: 32000, Silver:17000, Bronze: 14000 },
{ Country: "Russia", Gold: 27000, Silver:27000, Bronze: 38000 } ]);

]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Panel id="panel1" title="AxisRendererPlus Test" width="600" height="500">
<s:layout><s:VerticalLayout/></s:layout>
<mx:ColumnChart id="columnChart1" dataProvider="{medalsAC}" showDataTips="true"
width="100%" height="100%">
<mx:series>
<mx:ColumnSeries verticalAxis="{linearAxis}" displayName="Gold" yField="Gold" xField="Country"/>
<mx:ColumnSeries verticalAxis="{linearAxis}" displayName="Silver" yField="Silver" xField="Country"/>
<mx:ColumnSeries verticalAxis="{linearAxis}" displayName="Bronze" yField="Bronze" xField="Country"/>
</mx:series>
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="Country"/>
</mx:horizontalAxis>
<mx:verticalAxisRenderers>
<charts:AxisRendererPlus useThousandsSeparator="true" prefix="重量" suffix="㎏" precision="2">
<charts:formatUnit>
<charts:FormatUnit label="千" unit="{FormatUnit.THOUSAND}"/>
</charts:formatUnit>
<charts:axis>
<mx:LinearAxis id="linearAxis"/>
</charts:axis>
</charts:AxisRendererPlus>
</mx:verticalAxisRenderers>
</mx:ColumnChart>
<mx:Legend id="legend1" dataProvider="{columnChart1}" direction="horizontal"/>
</s:Panel>
</s:Application>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值