[Flex]给图表添加告警线(背景线,水平线)
作者:hangge | 2014-10-24 10:55
有时候我们需要在图表的背景上添加上参考线,用来比较。
在<mx:backgroundElements>节点中,添加自定义的ChartElement即可。
效果图如下:

图表代码如下:
使用到的DashedLines代码如下:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:hangge="com.hangge.*" creationComplete="init(event)">
<mx:Script>
<![CDATA[
import mx.charts.chartClasses.IAxisRenderer;
import mx.events.FlexEvent;
private var xml:XML = <data date='2014-06-02' flag='curve' toptop='' top='65.01' bottom="40" bottombottom="">
<item value='54.6' time='00:00' />
<item value='55.0' time='00:05' />
<item value='54.4' time='00:10' />
<item value='54.6' time='00:15' />
<item value='54.8' time='00:20' />
</data>
private function categoryLabelFunction(axisRenderer:IAxisRenderer, label:String):String {
return " "+label+" ";
}
protected function init(event:FlexEvent):void
{
chart1.dataProvider = xml.item;
vAxis.displayName = "湿度";
vAxis.maximum = 60;
vAxis.minimum = 50;
tt.yValue = 58;
bb.yValue = 52;
}
]]>
</mx:Script>
<mx:Canvas width="60%" height="60%" horizontalCenter="0" verticalCenter="0" backgroundColor="0xD0E0E4">
<mx:LineChart id="chart1" width="100%" height="100%" showDataTips="true">
<mx:backgroundElements>
<mx:GridLines direction="horizontal">
<mx:horizontalStroke>
<mx:Stroke color="0xFFFFFF" alpha="0.25"/>
</mx:horizontalStroke>
</mx:GridLines>
<hangge:DashedLines id="tt" lineColor="0xFF0000" displayName="上上限" yMax="100" yMin="0"/>
<hangge:DashedLines id="bb" lineColor="0xFF0000" displayName="下下限" yMax="100" yMin="0"/>
</mx:backgroundElements>
<mx:fill>
<mx:SolidColor color="0x000000" alpha="0"/>
</mx:fill>
<mx:horizontalAxis>
<mx:CategoryAxis id="hAxis" categoryField="@time" displayName="时间"/>
</mx:horizontalAxis>
<mx:horizontalAxisRenderers>
<mx:AxisRenderer axis="{hAxis}" tickPlacement="none" minorTickPlacement="none" color="0x000000" fontSize="14" fontFamily="微软雅黑" canDropLabels="true" labelFunction="categoryLabelFunction">
<mx:axisStroke>
<mx:Stroke weight="2" color="0xFFFFFF"/>
</mx:axisStroke>
</mx:AxisRenderer>
</mx:horizontalAxisRenderers>
<mx:verticalAxis>
<mx:LinearAxis id="vAxis" baseAtZero="false"/>
</mx:verticalAxis>
<mx:verticalAxisRenderers>
<mx:AxisRenderer axis="{vAxis}" tickPlacement="none" minorTickPlacement="none" fontSize="14" color="0x000000" fontFamily="微软雅黑">
<mx:axisStroke>
<mx:Stroke color="0xFFFFFF" weight="2"/>
</mx:axisStroke>
</mx:AxisRenderer>
</mx:verticalAxisRenderers>
<mx:series>
<mx:LineSeries id="ls" form="curve" xField="@time" yField="@value">
<mx:lineStroke>
<mx:Stroke color="0x00fff5"/>
</mx:lineStroke>
</mx:LineSeries>
</mx:series>
</mx:LineChart>
</mx:Canvas>
</mx:Application>
package com.hangge{
import flash.display.Graphics;
import flash.geom.Point;
import flash.text.TextField;
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();
}
/**
* 该线对应的y值
*/
private var _yValue:Number = NaN;
public function get yValue():Number {
return _yValue;
}
public function set yValue(value:Number):void {
_yValue = value;
invalidateDisplayList();
}
/**
* 该线对应的y轴最大值
*/
private var _yMax:Number = NaN;
public function get yMax():Number {
return _yMax;
}
public function set yMax(value:Number):void {
_yMax = value;
invalidateDisplayList();
}
/**
* 该线对应的y轴最小值
*/
private var _yMin:Number = NaN;
public function get yMin():Number {
return _yMin;
}
public function set yMin(value:Number):void {
_yMin = 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 {
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 posyValue:Number = (yValue - yMin) / (yMax - yMin) * 100;
// var y:Number = dataToLocal(0, yValue).y;
var y:Number = dataToLocal(0, posyValue).y;
var pFrom:Point = new Point(0, y);
var pTo:Point = new Point(w, y);
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);
}
/**
* 画虚线
* @param graphics 你懂的
* @param pFrom 起点
* @param pTo 终点
* @param length 实线段的长度
* @param gap 实线段的间距
* @param thickness 线的宽度
* @param color 线的颜色
*/
private 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;
}
}
}
}
全部评论(0)