在用flex面积图,curve 模式显示效果比较好,对其内部的显示过程很感兴趣,分析了一下源代码,自己写了一个模拟程序。
环境:
flash builder 4.6 ,flah player 12.0
主入口
<?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" minWidth="955" minHeight="600" creationComplete="application1_creationCompleteHandler(event)"> <fx:Script> <![CDATA[ import drawLine.DataItem; import drawLine.LineData; import drawLine.LineTest;
import mx.collections.ArrayCollection; import mx.events.FlexEvent; public var expenses:ArrayCollection = new ArrayCollection([ {Month:"1", server1:100, server2:50, server3:80}, {Month:"20", server1:101, server2:41,server3:81}, {Month:"30", server1:120, server2:41, server3:90}, {Month:"50", server1:131, server2:45, server3:92}, {Month:"80", server1:141, server2:60, server3:100}, {Month:"130", server1:161, server2:70, server3:101}, {Month:"210", server1:181, server2:80, server3:102}, {Month:"340", server1:300, server2:90, server3:103}, {Month:"550", server1:400, server2:100, server3:119}, {Month:"570", server1:500, server2:200, server3:120}, {Month:"600", server1:550, server2:300, server3:180}, {Month:"900", server1:600, server2:400, server3:200} ]); protected function application1_creationCompleteHandler(event:FlexEvent):void{ var line:LineTest=new LineTest(); var lineData:LineData=new LineData(); var itemArray:Array=new Array(); for(var i:int=0;i<expenses.length;i++) { var dataItem:DataItem=new DataItem(); dataItem.x=expenses[i]["Month"]; dataItem.y=expenses[expenses.length-i-1]["server1"]; itemArray.push(dataItem); } lineData.filteredCache=itemArray; line.data=lineData; line.x=1; line.y=1; line.width=955; line.height=600; this.addElement(line);
} ]]> </fx:Script> <fx:Declarations> <!-- 将非可视元素(例如服务、值对象)放在此处 --> </fx:Declarations>
</s:Application> |
package drawLine { public class DataItem { // x //----------------------------------
[Inspectable(environment="none")]
/** * The x value of this item converted into screen coordinates. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public var x:Number;
//---------------------------------- // y //----------------------------------
[Inspectable(environment="none")]
/** * The y value of this item converted into screen coordinates. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public var y:Number;
/** * The minimum value of this item converted into screen coordinates. The value of this field is <code>undefined</code> if the AreaSeries is not stacked and its <code>minField</code> property is not set. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public var min:Number;
public function DataItem() { } } } |
package drawLine { public class LineData { /** * The list of ChartItems representing the items * in the series's <code>dataProvider</code> that remain after filtering. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public var filteredCache:Array /* of ChartItem */; public function LineData(){
} } } |
package drawLine { import mx.charts.chartClasses.GraphicsUtilities; import mx.core.UIComponent; import mx.graphics.IFill; import mx.graphics.IStroke; import flash.display.Graphics; import flash.geom.Rectangle;
import mx.charts.chartClasses.GraphicsUtilities; import mx.core.IDataRenderer; import mx.graphics.IFill; import mx.graphics.IStroke; import mx.graphics.SolidColorStroke; import mx.skins.ProgrammaticSkin;
import spark.primitives.Graphic;
public class LineTest extends UIComponent { //-------------------------------------------------------------------------- // // Class variables // //--------------------------------------------------------------------------
/** * @private */ private static var noStroke:SolidColorStroke = new SolidColorStroke(0, 0, 0); /** * @private * Storage for the data property. */ private var _data:Object;
[Inspectable(environment="none")]
/** * The data that the AreaRenderer renders. * The AreaRenderer expects this property to be assigned an instance * of mx.charts.series.renderData.AreaRenderData. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get data():Object { return _data; }
/** * @private */ public function set data(value:Object):void { _data = value;
invalidateDisplayList(); } public function LineTest() { super(); this.setStyle("form","curve"); this.setStyle("areaFill",10861646); this.setStyle("areaStroke",new SolidColorStroke()); }
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight); var fill:IFill = GraphicsUtilities.fillFromStyle(getStyle("areaFill")); var stroke:IStroke = getStyle("areaStroke"); var form:String = getStyle("form");
var g:Graphics = graphics; g.clear();
if (!_data) return;
var boundary:Array /* of Object */ = _data.filteredCache; var n:int = boundary.length; if (n == 0) return;
var xMin:Number; var xMax:Number = xMin = boundary[0].x; var yMin:Number; var yMax:Number = yMin = boundary[0].y;
var v:Object;
for (var i:int = 0; i < n; i++) { v = boundary[i];
xMin = Math.min(xMin, v.x); yMin = Math.min(yMin, v.y); xMax = Math.max(xMax, v.x); yMax = Math.max(yMax, v.y);
if (!isNaN(v.min)) { yMin = Math.min(yMin, v.min); yMax = Math.max(yMax, v.min); } }
if (fill) fill.begin(g, new Rectangle(xMin, yMin, xMax - xMin, yMax - yMin),null);
GraphicsUtilities.drawPolyLine(g, boundary, 0, n, "x", "y", stroke, form);
g.lineStyle(0,0,0);
// if (boundary[0].element.minField != null && boundary[0].element.minField != "") // { // g.lineTo(boundary[n - 1].x, boundary[n - 1].min); // // GraphicsUtilities.drawPolyLine(g, boundary, n - 1, -1, // "x", "min", noStroke, form, false); // } // else // { // g.lineTo(boundary[n - 1].x, _data.renderedBase); // g.lineTo(boundary[0].x, _data.renderedBase); // }
g.lineStyle(0, 0, 0); g.lineTo(boundary[0].x, boundary[0].y);
g.endFill(); }
} } |