动态曲线图 flex实现的说明
Author: Allan(吴进刚)
其实现在回想起来很简单 无非就是用到了 flex 的 mx:LineChart组件,下面详细的说明下该组件下面是如何实现x轴,y轴的 刻度显示 曲线的实现,数据绑定等等。。
首先看如下代码:
<mx:LineChart id="mychart" height="23%" width="50%"
paddingRight="5" paddingLeft="5"
showDataTips="true" seriesFilters="[]" selectionMode="multiple" doubleClickEnabled="true"
change="onZoom(event)"
chartDoubleClick="onReset(event)" >
<mx:horizontalAxis>
<mx:DateTimeAxis id="hAxis" dataUnits="seconds" interval="5" minimum="{minDate}" maximum="{maxDate}" labelFunction="mylabel" alignLabelsToUnits="false" title="Time"/>
</mx:horizontalAxis>
<mx:horizontalAxisRenderers>
<mx:AxisRenderer axis="{hAxis}" placement="left" />
</mx:horizontalAxisRenderers>
<mx:verticalAxis>
<mx:LinearAxis id="vAxis" baseAtZero="false" minorInterval="10" interval="5" title="Value"/>
</mx:verticalAxis>
<mx:verticalAxisRenderers>
<mx:AxisRenderer axis="{vAxis}" styleName="linedNumericAxis"/>
</mx:verticalAxisRenderers>
<mx:series>
<mx:LineSeries yField="valueTest" xField="date" displayName="TestData" dataProvider="{this.testDatas}" form="curve"/>
</mx:series>
</mx:LineChart>
mx:LineChart : 用来构造整个曲线图;
showDataTips="true":show details of data point
selectionMode="multiple":选择多个数据点,可以是0个或者1个
doubleClickEnabled="true":是否允许双击chart
change="onZoom(event)":Dispatched when the selection changes in the chart
chartDoubleClick="onReset(event)":
mx:horizontalAxis:用来定义X轴;
mx:DateTimeAxis:时间轴;
dataUnits="seconds":milliseconds seconds minutes hours days weeks months years
interval="5":间隔时间
minimum="{minDate}":起始时间,绑定到 minDate
maximum="{maxDate}":结束时间,绑定到 maxDate
labelFunction="mylabel":x轴显示的值,有函数 mylabel 返回
alignLabelsToUnits="false":使x轴不标值点从0开始
mx:horizontalAxisRenderers:定义一组渲染X轴的特效;
mx:AxisRenderer:定义特效的;
axis="{hAxis}"
mx:verticalAxis:用来定义Y轴;
mx:verticalAxisRenderers:定义一组渲染Y轴的特效;
mx:series:定义一组LineSeries 也就是曲线或者点。。;
mx:LineSeries:定义要展现的数据曲线,可以定义多条曲线;
yField="valueTest":绑定的数据源中的key为valueTest的值
xField="date":绑定的数据源中的key为date的值
dataProvider="{this.testDatas}":绑定数据testDatas
form="curve":趋势图显示为曲线,可以为horizontal vertical 等等 默认为segment
再来看Action Script 代码:
<fx:Script>
<![CDATA[
import flash.utils.setInterval;
import mx.charts.chartClasses.AxisLabelSet;
import mx.charts.chartClasses.IAxis;
import mx.charts.events.ChartEvent;
import mx.charts.events.ChartItemEvent;
import mx.charts.renderers.CircleItemRenderer;
import mx.charts.series.LineSeries;
import mx.charts.series.items.LineSeriesItem;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.formatters.DateFormatter;
import mx.rpc.events.ResultEvent;
[Bindable]
public var testDatas:ArrayCollection;
[Bindable]
private var maxDate:Date;
[Bindable]
private var minDate:Date;
private var timer:Timer;
private var dateFormat:DateFormatter = new DateFormatter();
private var dateVar:Date;
private function init():void {
dateFormat.formatString = "HH:NN:SS";
minDate = new Date();
var dx:Date = new Date();
dx.setMinutes(dx.getMinutes()+1, dx.getSeconds(), dx.getMilliseconds());
maxDate = dx;
dateVar = new Date();
testDatas = new ArrayCollection([{date: dateVar, valueTest: 101.71} ]);
//以指定的时间间隔执行函数
// private static const MINISECENDS:int=1000;
// setInterval(getDatas,MINISECENDS);
//这里用的Timer定时
timer = new Timer(1000);
timer.addEventListener(TimerEvent.TIMER, getDatas)
timer.start();
}
private function mylabel(labelValue:Object, previousValue:Object, d:IAxis):String {
var str:String = dateFormat.format(labelValue);
return str;
}
//组装 testDatas数据
private function getDatas(et:Event):void {
var valueTestValue:int = Math.random()*50;
var dm:Date = new Date();
dm.setTime(dateVar.getTime());
dm.setSeconds(dm.getSeconds()+1, dm.getMilliseconds());
dateVar = dm;
if (dateVar.getTime()>maxDate.getTime()) {
maxDate = dateVar;
var dx:Date = new Date();
dx.setMinutes(dx.getMinutes()-1, dx.getSeconds(), dx.getMilliseconds());
minDate = dx;
}
testDatas.addItem({date: dateVar, valueTest: valueTestValue});
}
import mx.managers.PopUpManager;
import test.GraphTest1SelectTime;
private function showAlertWindow():void{
var myPanel:GraphTest1SelectTime = GraphTest1SelectTime(PopUpManager.createPopUp(this, GraphTest1SelectTime, true)); // 这里第三个参数 true 表示: 弹出myPanel窗口后, 是否可以对父级操作, 值为true时, 就会产生背景模糊的效果, 并不能对父级的东西进行操作
myPanel.x = 420;
myPanel.y = 170;
}
private var canReset:Boolean = false;
//放大选择的焦点区域的函数
private function onZoom(event:ChartItemEvent):void
{
var lc:LineChart = event.target as LineChart;
for each (var ls:LineSeries in lc.series)
{
var ac:ArrayCollection = new ArrayCollection();
var dp:ArrayCollection = ls.dataProvider as ArrayCollection;
for each (var lsi:LineSeriesItem in ls.selectedItems)
{
ac.addItem(lsi.item);
}
ls.dataProvider = ac;
}
lc.clearSelection();
canReset = true;
}
//only need reset after zoom
private function onReset(event:ChartEvent):void
{
if(canReset)
{
var lc:LineChart = event.target as LineChart;
for (var i:int = 0; i < lc.series.length; i++)
{
var ls:LineSeries = lc.series[i] as LineSeries;
ls.dataProvider = testDatas;
}
canReset = false;
}
}
]]>
</fx:Script>
这里面定义了绑定的数据对象,和 被调用的函数,可以自行去查看,有说明备注。
最后说明如何利用blazeds与 Java server 通信,实时展现后台的数据曲线图:
请看代码:
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
<mx:ChannelSet id="cs">
<mx:AMFChannel url="../messagebroker/amf"/>
</mx:ChannelSet>
<mx:RemoteObject id="graphTest1FeedStarter" destination="graphTest1FeedStarter" channelSet="{cs}"/>
<mx:ChannelSet id="cs2">
<!-- <mx:StreamingAMFChannel url="../messagebroker/streamingamf"/> -->
<mx:AMFChannel url="../messagebroker/amflongpolling"/>
<mx:AMFChannel url="../messagebroker/amfpolling"/>
</mx:ChannelSet>
<mx:Consumer id="consumer" destination="graphTest1-feed" channelSet="{cs2}"
message="messageHandler(event.message)"/>
</fx:Declarations>
mx:ChannelSet:定义一组频道;
mx:AMFChannel:定义一个频道;
mx:RemoteObject:定义一个远程对象;
destination="graphTest1FeedStarter":选定一个server定义的对象;
channelSet="{cs}":选定一个频道;
mx:Consumer:订阅目标来接收消息;
destination="graphTest1-feed":选定一个server定义的对象;
channelSet="{cs2}":选定一个频道;
message="messageHandler(event.message)":接收到消息时分派;
下面是分派消息的函数:为曲线图绑定的数据源testDatas提供实时数据取代上面用Timer订阅数据;
import mx.messaging.messages.IMessage;
private function messageHandler(message:IMessage):void {
var dm:Date = new Date();
dm.setTime(dateVar.getTime());
dm.setSeconds(dm.getSeconds()+1, dm.getMilliseconds());
dateVar = dm;
if (dateVar.getTime()>maxDate.getTime()) {
maxDate = dateVar;
var dx:Date = new Date();
dx.setMinutes(dx.getMinutes()-1, dx.getSeconds(), dx.getMilliseconds());
minDate = dx;
}
testDatas.addItem({date: dateVar, valueTest: message.body});
}