Flex4 用LineChart实现实时曲线图,并在其中添加自定义的虚线水平线

本示例首先是为了显示实时曲线。然后呢,要显示个水平线,比如我要显示一个变量的变化过程,但它有一个标准值,就可以用该种方式。

示例:

[flash=600,500]https://dl.dropbox.com/u/38216791/flex/samples/runtimeChart/samples.swf[/flash]

然后是代码:
先看Application:


xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:chartClasses="lip.charts.chartClasses.*">


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;
}

]]>





0.3










verticalCenter="0" dataProvider="{ac}" >






















接下来是里面的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;
}
}
}
}


代码不太多,就不详细解释了。

你可能感兴趣的:(Flex自定义控件,Flex示例)