首页 > 代码库 > Linechart + Datagrid 互动展示数据 (Linechart自定义数据点选择线)
Linechart + Datagrid 互动展示数据 (Linechart自定义数据点选择线)
如上图示,在linechart中添加红色Y线,拖动该线的过程中,经过数据点时,会实时更新datagrid中对应的X、Y值数据。
实现要点:
1.linechart添加Y线
继承mx.charts.chartClasses.ChartElement,自定义Y线。
package { 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(); } private var _yValue:Number = NaN; private var _xValue:Date = null; public function get xValue():Date { return _xValue; } public function set xValue(value:Date):void { _xValue = value; invalidateDisplayList(); } public function get yValue():Number { return _yValue; } public function set yValue(value:Number):void { _yValue = value; invalidateDisplayList(); } /** * 实线部分的长度 * @default 10 */ public var length:Number = 10; /** * 空白部分的长度 * @default 5 */ public var gap:Number = 0; /** * 线条的宽度 * @default 1 */ public var lineThickness:Number = 3; /** * 线条的颜色 * @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(xValue == null) { return; } var w:Number = unscaledWidth; var h:Number = unscaledHeight; var vAxis:IAxis = CartesianChart(this.chart).verticalAxis; var x:Number = dataToLocal(xValue,0).x; var pFrom:Point = new Point(x,0); var pTo:Point = new Point(x,h); GraphicUtils.drawDashed(g, pFrom, pTo, this.length, this.gap, this.lineThickness, this.lineColor); label.text = (displayName ? (displayName + " : ") : "") + xValue; label.x = x > 21 ? x - 21 : x + 1; label.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); } } }
该类中主要用到dataTransform,他提供了数据点与坐标空间的对应转换,主类中通过xValue将Y线处的x值传入,通过该方法转换为Y线需要绘制的坐标位置。
该类用到工具类GraphicUtils
package { 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; } } } }
2、datagrid对应样式的定义
请参考博文:datagrid样式
3、组件主类
<?xml version="1.0" encoding="utf-8"?> <s:BorderContainer 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:customcomponent="com.bjrz.view.centerview.customcomponent.*" xmlns:amcharts="http://www.amcharts.com/com_internal" width="100%" height="100%" creationComplete="generateChartData()" xmlns:local="*"> <fx:Script> <![CDATA[ import mx.charts.ChartItem; import mx.charts.chartClasses.IAxis; import mx.charts.chartClasses.Series; import mx.charts.series.items.LineSeriesItem; import mx.collections.ArrayCollection; import mx.controls.Alert; import mx.formatters.DateFormatter; [Bindable] private var attributes:ArrayCollection = new ArrayCollection( [{lineColor:"0xFF6600", dataItem:"label",time:"北京", currentValue:"label",unit:"北京", show:"true",describe:"北京"}, {lineColor:"0x00ff00", dataItem:"label",time:"北京", currentValue:"label",unit:"北京", show:"true",describe:"北京"}]); private var dateFormat:DateFormatter = new DateFormatter(); private function generateChartData():void { dateFormat.formatString = "HH:NN:SS"; } [Bindable] private var expensesAC:ArrayCollection = new ArrayCollection( [ { Month: "Tue May 20 16:23:50 GMT+0800 2014", Profit: 2000, Expenses: 1500, Amount: 450 }, { Month: "Tue May 20 16:23:51 GMT+0800 2014", Profit: 1000, Expenses: 200, Amount: 600 }, { Month: "Tue May 20 16:23:52 GMT+0800 2014", Profit: 1500, Expenses: 500, Amount: 300 }, { Month: "Tue May 20 16:23:53 GMT+0800 2014", Profit: 1800, Expenses: 1200, Amount: 900 }, { Month: "Tue May 20 16:23:54 GMT+0800 2014", Profit: 2400, Expenses: 575, Amount: 500 }, { Month: "Tue May 20 16:23:55 GMT+0800 2014", Profit: 1000, Expenses: 200, Amount: 600 }, { Month: "Tue May 20 16:23:56 GMT+0800 2014", Profit: 1500, Expenses: 500, Amount: 300 }, { Month: "Tue May 20 16:23:57 GMT+0800 2014", Profit: 1800, Expenses: 1200, Amount: 900 }, { Month: "Tue May 20 16:23:58 GMT+0800 2014", Profit: 2400, Expenses: 575, Amount: 500 }, { Month: "Tue May 20 16:23:59 GMT+0800 2014", Profit: 1000, Expenses: 200, Amount: 600 }, { Month: "Tue May 20 16:24:00 GMT+0800 2014", Profit: 1500, Expenses: 500, Amount: 300 }, { Month: "Tue May 20 16:24:01 GMT+0800 2014", Profit: 1800, Expenses: 1200, Amount: 900 }, { Month: "Tue May 20 16:24:02 GMT+0800 2014", Profit: 2400, Expenses: 575, Amount: 500 }, { Month: "Tue May 20 16:24:03 GMT+0800 2014", Profit: 1000, Expenses: 200, Amount: 600 }, { Month: "Tue May 20 16:24:04 GMT+0800 2014", Profit: 1500, Expenses: 500, Amount: 300 }, { Month: "Tue May 20 16:24:05 GMT+0800 2014", Profit: 1800, Expenses: 1200, Amount: 900 }, { Month: "Tue May 20 16:24:06 GMT+0800 2014", Profit: 2400, Expenses: 575, Amount: 500 }, { Month: "Tue May 20 16:24:07 GMT+0800 2014", Profit: 1000, Expenses: 200, Amount: 600 }, { Month: "Tue May 20 16:24:08 GMT+0800 2014", Profit: 1500, Expenses: 500, Amount: 300 }, { Month: "Tue May 20 16:24:09 GMT+0800 2014", Profit: 1800, Expenses: 1200, Amount: 900 }, { Month: "Tue May 20 16:24:10 GMT+0800 2014", Profit: 2400, Expenses: 575, Amount: 500 }, { Month: "Tue May 20 16:24:11 GMT+0800 2014", Profit: 1000, Expenses: 200, Amount: 600 }, { Month: "Tue May 20 16:24:12 GMT+0800 2014", Profit: 1500, Expenses: 500, Amount: 300 }, { Month: "Tue May 20 16:24:13 GMT+0800 2014", Profit: 1800, Expenses: 1200, Amount: 900 }, { Month: "Tue May 20 16:24:14 GMT+0800 2014", Profit: 2400, Expenses: 575, Amount: 500 }, { Month: "Tue May 20 16:24:15 GMT+0800 2014", Profit: 1000, Expenses: 200, Amount: 600 }, { Month: "Tue May 20 16:24:16 GMT+0800 2014", Profit: 1500, Expenses: 500, Amount: 300 }, { Month: "Tue May 20 16:24:17 GMT+0800 2014", Profit: 1800, Expenses: 1200, Amount: 900 }, { Month: "Tue May 20 16:24:18 GMT+0800 2014", Profit: 2400, Expenses: 575, Amount: 500 }, { Month: "Tue May 20 16:24:19 GMT+0800 2014", Profit: 1000, Expenses: 200, Amount: 600 }]); [Bindable] private var expensesAC2:ArrayCollection = new ArrayCollection( [ { Month: "Tue May 20 16:23:50 GMT+0800 2014", Profit: 2100, Expenses: 1500, Amount: 460 }, { Month: "Tue May 20 16:23:51 GMT+0800 2014", Profit: 1100, Expenses: 200, Amount: 660 }, { Month: "Tue May 20 16:23:52 GMT+0800 2014", Profit: 1100, Expenses: 500, Amount: 340 }, { Month: "Tue May 20 16:23:53 GMT+0800 2014", Profit: 1100, Expenses: 1200, Amount: 960 }, { Month: "Tue May 20 16:23:54 GMT+0800 2014", Profit: 2100, Expenses: 575, Amount: 500 }, { Month: "Tue May 20 16:23:55 GMT+0800 2014", Profit: 1100, Expenses: 200, Amount: 630 }, { Month: "Tue May 20 16:23:56 GMT+0800 2014", Profit: 1100, Expenses: 500, Amount: 360 }, { Month: "Tue May 20 16:23:57 GMT+0800 2014", Profit: 1100, Expenses: 1200, Amount: 930 }, { Month: "Tue May 20 16:23:58 GMT+0800 2014", Profit: 2400, Expenses: 575, Amount: 500 }, { Month: "Tue May 20 16:23:59 GMT+0800 2014", Profit: 1100, Expenses: 200, Amount: 600 }, { Month: "Tue May 20 16:24:00 GMT+0800 2014", Profit: 1500, Expenses: 500, Amount: 320 }, { Month: "Tue May 20 16:24:01 GMT+0800 2014", Profit: 1800, Expenses: 1200, Amount: 300 }, { Month: "Tue May 20 16:24:02 GMT+0800 2014", Profit: 2410, Expenses: 575, Amount: 500 }, { Month: "Tue May 20 16:24:03 GMT+0800 2014", Profit: 1010, Expenses: 200, Amount: 650 }, { Month: "Tue May 20 16:24:04 GMT+0800 2014", Profit: 1500, Expenses: 500, Amount: 360 }, { Month: "Tue May 20 16:24:05 GMT+0800 2014", Profit: 1100, Expenses: 1200, Amount: 900 }, { Month: "Tue May 20 16:24:06 GMT+0800 2014", Profit: 2100, Expenses: 575, Amount: 500 }, { Month: "Tue May 20 16:24:07 GMT+0800 2014", Profit: 1000, Expenses: 200, Amount: 600 }, { Month: "Tue May 20 16:24:08 GMT+0800 2014", Profit: 1500, Expenses: 500, Amount: 360 }, { Month: "Tue May 20 16:24:09 GMT+0800 2014", Profit: 1800, Expenses: 1200, Amount: 900 }, { Month: "Tue May 20 16:24:10 GMT+0800 2014", Profit: 2400, Expenses: 575, Amount: 570 }, { Month: "Tue May 20 16:24:11 GMT+0800 2014", Profit: 1100, Expenses: 200, Amount: 600 }, { Month: "Tue May 20 16:24:12 GMT+0800 2014", Profit: 1100, Expenses: 500, Amount: 300 }, { Month: "Tue May 20 16:24:13 GMT+0800 2014", Profit: 1100, Expenses: 1200, Amount: 940 }, { Month: "Tue May 20 16:24:14 GMT+0800 2014", Profit: 2400, Expenses: 575, Amount: 540 }, { Month: "Tue May 20 16:24:15 GMT+0800 2014", Profit: 1000, Expenses: 200, Amount: 600 }, { Month: "Tue May 20 16:24:16 GMT+0800 2014", Profit: 1500, Expenses: 500, Amount: 340 }, { Month: "Tue May 20 16:24:17 GMT+0800 2014", Profit: 1100, Expenses: 1200, Amount: 940 }, { Month: "Tue May 20 16:24:18 GMT+0800 2014", Profit: 2400, Expenses: 575, Amount: 500 }, { Month: "Tue May 20 16:24:19 GMT+0800 2014", Profit: 1100, Expenses: 200, Amount: 640 }]); protected function dashedlines1_mouseDownHandler(event:MouseEvent):void { this.addEventListener(MouseEvent.MOUSE_MOVE,dashedLine_mouseMoveHandler); this.addEventListener(MouseEvent.MOUSE_UP,dashedlines1_mouseUpHandler); } protected function dashedlines1_mouseUpHandler(event:MouseEvent):void { this.removeEventListener(MouseEvent.MOUSE_MOVE,dashedLine_mouseMoveHandler); this.removeEventListener(MouseEvent.MOUSE_UP,dashedlines1_mouseUpHandler); } [Bindable] private var linePosition:Number = 2; protected function dashedLine_mouseMoveHandler(event:MouseEvent):void { dashedLine.xValue = http://www.mamicode.com/new Date(Number((((linechart.mouseX - 50)*((hAxis.maximum as Date).time-(hAxis.minimum as Date).time)/(linechart.width-50)>
该类中,主要方法是针对Y线的拖拽处理。基本拖拽处理不再赘述。在mouseMove的处理中,需要对xValue执行重新赋值,以便刷新绘制Y线。因为linechart只提供了数据点转坐标空间,没有找到坐标空间转数据点的方法。所以需要将鼠标位置mouseX通过计算转化为数据点x,然后作为xValue传入。
同时,根据数据点x获取对应的y值。这是出现一个问题:
mouseX是连续的,而数据点非连续。
因为我的需求中linechart数据点十分密集,极近于连续点。所以我采用的方法是,将在计算转化的时候,取近似值。只将时间为整秒的数据做转化传入。这样并不影响最终使用效果。如果有更好的处理方式,望留言告知。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。