本示例首先是为了显示实时曲线。然后呢,要显示个水平线,比如我要显示一个变量的变化过程,但它有一个标准值,就可以用该种方式。
示例:
然后是代码:
先看Application:
<?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/mx" xmlns:chartClasses="lip.charts.chartClasses.*">
<fx:Script>
<![CDATA[
import lip.utils.DateFormatter;
import mx.collections.ArrayCollection;
import mx.utils.ObjectProxy;
private static const DELAY:int = 1000;
private static const MAX_COUNT:int = 10;
[Bindable]
private var ac:ArrayCollection;
private var timer:Timer;
protected function startCalc(event:MouseEvent):void
{
if(!timer)
{
timer = new Timer(DELAY);
timer.addEventListener(TimerEvent.TIMER, timer_timerHandler);
}
timer.start();
}
protected function stopCalc(event:MouseEvent):void
{
if(timer)
timer.stop();
ac = null;
}
protected function timer_timerHandler(event:TimerEvent):void
{
var now:Date = new Date();
var nowTime:String;
if(!ac)
{
ac = new ArrayCollection();
now.setTime(now.time - 1000 * MAX_COUNT);
for (var i:int = 0; i < MAX_COUNT; i++)
{
nowTime = DateFormatter.getInstance().formatTime(now);
ac.addItem(new ObjectProxy({time:nowTime, gas:0}));
now.setTime(now.time + 1000);
}
}
nowTime = DateFormatter.getInstance().formatTime(now);
var item:ObjectProxy = new ObjectProxy({time:nowTime, gas:Math.round(Math.random() * 100) * .01});
if(ac.length < 10)
{
ac.addItem(item);
}
else
{
ac.removeItemAt(0);
ac.addItem(item);
}
trace(item.time, ":", item.gas);
}
protected function changeDashedLine(event:MouseEvent):void
{
nn = Math.round((Math.random() / 5 + 0.8) * 100) * .01;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
<mx:SeriesInterpolate id="effect" duration="1000" />
<fx:Number id="nn">0.3</fx:Number>
</fx:Declarations>
<s:Panel width="600" height="500" title="测试实时曲线">
<s:controlBarContent>
<s:HGroup width="100%" height="20" horizontalAlign="center" verticalAlign="middle">
<s:Button label="start" click="startCalc(event)"/>
<s:Button label="stop" click="stopCalc(event)"/>
<s:Button label="change dashed line" click="changeDashedLine(event)"/>
</s:HGroup>
</s:controlBarContent>
<mx:LineChart id="chart" width="500" height="400" horizontalCenter="0" showDataTips="true"
verticalCenter="0" dataProvider="{ac}" >
<mx:backgroundElements>
<mx:GridLines gridDirection="both"/>
<chartClasses:DashedLines lineColor="0xFF0000" yValue="{nn}"/>
</mx:backgroundElements>
<mx:horizontalAxis>
<mx:CategoryAxis categoryField="time" displayName="Time" title="时间" />
</mx:horizontalAxis>
<mx:verticalAxis>
<mx:LinearAxis minimum="0" maximum="1"/>
</mx:verticalAxis>
<mx:series>
<mx:LineSeries displayName="瓦斯" xField="time" yField="gas" form="curve"/>
</mx:series>
</mx:LineChart>
</s:Panel>
</s:Application>
接下来是里面的DashedLines:
package lip.charts.chartClasses
{
import flash.display.Graphics;
import flash.geom.Point;
import lip.utils.GraphicUtils;
import mx.charts.chartClasses.CartesianChart;
import mx.charts.chartClasses.CartesianTransform;
import mx.charts.chartClasses.ChartElement;
import mx.charts.chartClasses.ChartState;
import mx.charts.chartClasses.IAxis;
public class DashedLines extends ChartElement
{
public function DashedLines()
{
super();
}
private var _yValue:Number = NaN;
/**
* 该线对应的y值
*/
public function get yValue():Number
{
return _yValue;
}
/**
* @private
*/
public function set yValue(value:Number):void
{
_yValue = value;
invalidateDisplayList();
}
/**
* 实线部分的长度
* @default 10
*/
public var length:Number = 10;
/**
* 空白部分的长度
* @default 5
*/
public var gap:Number = 5;
/**
* 线条的宽度
* @default 1
*/
public var lineThickness:Number = 1;
/**
* 线条的颜色
* @default 黑色
*/
public var lineColor:uint = 0;
private var _displayName:String;
/**
* 该线所对应的数值名称(平均值,最大值等等)
* @default
*/
public function get displayName():String
{
return _displayName;
}
/**
* @private
*/
public function set displayName(value:String):void
{
_displayName = value;
invalidateDisplayList();
}
protected var label:TextField;
override protected function createChildren():void
{
// TODO Auto Generated method stub
super.createChildren();
if(!label)
{
label = new TextField();
label.mouseEnabled = false;
addChild(label);
}
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if (!chart||
chart.chartState == ChartState.PREPARING_TO_HIDE_DATA ||
chart.chartState == ChartState.HIDING_DATA)
{
return;
}
var g:Graphics = this.graphics;
g.clear();
// 如果没有设置数据,不显示
if(isNaN(yValue))
{
return;
}
var w:Number = unscaledWidth;
var h:Number = unscaledHeight;
var vAxis:IAxis = CartesianChart(this.chart).verticalAxis;
var y:Number = dataToLocal(0, yValue).y;
var pFrom:Point = new Point(0, y);
var pTo:Point = new Point(w, y);
GraphicUtils.drawDashed(g, pFrom, pTo, this.length, this.gap, this.lineThickness, this.lineColor);
label.text = (displayName ? (displayName + " : ") : "") + yValue;
label.x = 1;
label.y = y > 21 ? y - 21 : y + 1;
}
// 这个方法复制自LineSeries
override public function dataToLocal(... dataValues):Point
{
var data:Object = {};
var da:Array /* of Object */ = [ data ];
var n:int = dataValues.length;
if (n > 0)
{
data["d0"] = dataValues[0];
dataTransform.getAxis(CartesianTransform.HORIZONTAL_AXIS).
mapCache(da, "d0", "v0");
}
if (n > 1)
{
data["d1"] = dataValues[1];
dataTransform.getAxis(CartesianTransform.VERTICAL_AXIS).
mapCache(da, "d1", "v1");
}
dataTransform.transformCache(da,"v0","s0","v1","s1");
return new Point(data.s0 + this.x,
data.s1 + this.y);
}
}
}
还有其中用到的GraphicUtils.drawDashed()方法:
package lip.utils
{
import flash.display.Graphics;
import flash.geom.Point;
/**
* 一些绘图相关的方法
* @author lip
*/
public class GraphicUtils
{
public function GraphicUtils()
{
}
/**
* 画虚线
* @param graphics 你懂的
* @param pFrom 起点
* @param pTo 终点
* @param length 实线段的长度
* @param gap 实线段的间距
* @param thickness 线的宽度
* @param color 线的颜色
*/
public static function drawDashed(graphics:Graphics, pFrom:Point, pTo:Point, length:Number = 5, gap:Number = 5, thickness:Number = 1, color:uint = 0):void
{
var max:Number = Point.distance(pFrom, pTo);
var l:Number = 0;
var p3:Point;
var p4:Point;
graphics.lineStyle(thickness, color);
while (l < max)
{
p3 = Point.interpolate(pTo, pFrom, l / max);
l += length;
if (l > max)
l = max;
p4 = Point.interpolate(pTo, pFrom, l / max);
graphics.moveTo(p3.x, p3.y)
graphics.lineTo(p4.x, p4.y)
l += gap;
}
}
}
}
代码不太多,就不详细解释了。