📄 chart.as
字号:
/** * Returns the index within this plot area of the input ISeries object. * * @param series a series that is displayed in this plot area. * @return the index of the input series */ public function seriesToIndex(series:ISeries):int { return this.series.indexOf(series); } /** * Returns the ISeries object at the specified index. * * @param index the index of the series to return * @return the series that appears at the input index or null if out of bounds */ public function indexToSeries(index:int):ISeries { if(index < 0 || index >= this.series.length) return null; return this.series[index]; } //-------------------------------------- // Protected Methods //-------------------------------------- /** * @private */ override protected function configUI():void { super.width = 400; super.height = 300; super.configUI(); this.content = new Sprite(); this.addChild(this.content); this.dataTip = new DataTipRenderer(); this.dataTip.visible = false; this.addChild(this.dataTip); } /** * @private */ override protected function draw():void { var dataInvalid:Boolean = this.isInvalid(InvalidationType.DATA); var stylesInvalid:Boolean = this.isInvalid(InvalidationType.STYLES); var sizeInvalid:Boolean = this.isInvalid(InvalidationType.SIZE); if(stylesInvalid || dataInvalid) { this.refreshSeries(); } //update the background if needed if(stylesInvalid) { if(this.background) { this.removeChild(this.background); } var skinClass:Object = this.getStyleValue("backgroundSkin"); this.background = UIComponentUtil.getDisplayObjectInstance(this, skinClass); this.addChildAt(this.background, 0); } if(this.background && (stylesInvalid || sizeInvalid)) { this.background.width = this.width; this.background.height = this.height; //force the background to redraw if it is a UIComponent if(this.background is UIComponent) { (this.background as UIComponent).drawNow(); } } if(this.dataTip is UIComponent) { var dataTip:UIComponent = UIComponent(this.dataTip); this.copyStylesToChild(dataTip, DATA_TIP_STYLES); dataTip.drawNow(); } super.draw(); } /** * Analyzes the input data and smartly converts it to the correct ISeries type * required for drawing. Adds new ISeries objects to the display list and removes * unused series objects that no longer need to be drawn. */ protected function refreshSeries():void { var modifiedData:Object = this._dataProvider; //loop through each series and convert it to the correct data type if(modifiedData is Array) { var arrayData:Array = (modifiedData as Array).concat(); var seriesCount:int = arrayData.length; var foundIncompatibleData:Boolean = false; for(var i:int = 0; i < seriesCount; i++) { var currentItem:Object = arrayData[i]; if(currentItem is Array || currentItem is XMLList) { var itemSeries:ISeries = new this.defaultSeriesType(); if(currentItem is Array) { itemSeries.dataProvider = (currentItem as Array).concat(); } else if(currentItem is XMLList) { itemSeries.dataProvider = (currentItem as XMLList).copy(); } arrayData[i] = itemSeries; } else if(!(currentItem is ISeries)) { //we only support Array, XMLList, and ISeries //anything else means that we should restore the original data var originalData:Array = (modifiedData as Array).concat(); modifiedData = new this.defaultSeriesType(originalData); foundIncompatibleData = true; break; } } if(!foundIncompatibleData) { modifiedData = arrayData; } } //attempt to turn a string into XML if(modifiedData is String) { try { modifiedData = new XML(modifiedData); } catch(error:Error) { //this isn't a valid xml string, so ignore it return; } } //we need an XMLList, so get the elements if(modifiedData is XML) { modifiedData = (modifiedData as XML).elements(); } //convert the XMLList to a series if(modifiedData is XMLList) { modifiedData = new this.defaultSeriesType(modifiedData); } //we should have an ISeries object by now, so put it in an Array if(modifiedData is ISeries) { //if the main data is a series, put it in an array modifiedData = [modifiedData]; } //if it's not an array, we have bad data, so ignore it if(!(modifiedData is Array)) { return; } arrayData = modifiedData as Array; seriesCount = this.series.length; for(i = 0; i < seriesCount; i++) { var currentSeries:ISeries = this.series[i] as ISeries; if(arrayData.indexOf(currentSeries) < 0) { //if the series no longer exists, remove it from the display list and stop listening to it this.content.removeChild(DisplayObject(currentSeries)); currentSeries.removeEventListener("dataChange", seriesDataChangeHandler); currentSeries.removeEventListener(ChartEvent.ITEM_ROLL_OVER, chartItemRollOver); currentSeries.removeEventListener(ChartEvent.ITEM_ROLL_OUT, chartItemRollOut); currentSeries.chart = null; } } //rebuild the series Array this.series = []; seriesCount = arrayData.length; for(i = 0; i < seriesCount; i++) { currentSeries = arrayData[i] as ISeries; this.series.push(currentSeries); if(!this.contains(DisplayObject(currentSeries))) { //if this is a new series, add it to the display list and listen for events currentSeries.addEventListener("dataChange", seriesDataChangeHandler, false, 0, true); currentSeries.addEventListener(ChartEvent.ITEM_ROLL_OVER, chartItemRollOver, false, 0, true); currentSeries.addEventListener(ChartEvent.ITEM_ROLL_OUT, chartItemRollOut, false, 0, true); currentSeries.chart = this; this.content.addChild(DisplayObject(currentSeries)); } DisplayObject(currentSeries).x = 0; DisplayObject(currentSeries).y = 0; //make sure the series are displayed in the correct order this.content.setChildIndex(DisplayObject(currentSeries), this.content.numChildren - 1); //update the series styles this.copyStylesToSeries(currentSeries, ALL_SERIES_STYLES); if(currentSeries is UIComponent) { this.copyStylesToChild(UIComponent(currentSeries), SHARED_SERIES_STYLES); } } } /** * @private * Refreshes the legend's data provider. */ protected function updateLegend():void { if(!this.legend) return; var legendData:Array = []; var seriesCount:int = this.series.length; for(var i:int = 0; i < seriesCount; i++) { var series:ISeries = ISeries(this.series[i]); if(series is ILegendItemSeries) { var itemData:LegendItemData = ILegendItemSeries(series).createLegendItemData(); itemData.label = itemData.label ? itemData.label : i.toString(); legendData.push(itemData); } else if(series is ICategorySeries) { legendData = legendData.concat(ICategorySeries(series).createLegendItemData()); } } this.legend.dataProvider = legendData; if(UIComponent.inCallLaterPhase) { UIComponent(this.legend).drawNow(); } } /** * @private * Tranfers the chart's styles to the ISeries components it contains. These styles * must be of the type Array, and the series index determines the index of the value * to use from that Array. If the chart contains more ISeries components than there * are values in the Array, the indices are reused starting from zero. */ protected function copyStylesToSeries(child:ISeries, styleMap:Object):void { var index:int = this.series.indexOf(child); var childComponent:UIComponent = child as UIComponent; for(var n:String in styleMap) { var styleValues:Array = this.getStyleValue(styleMap[n]) as Array; //if it doesn't exist, ignore it and go with the defaults for this series if(styleValues == null || styleValues.length == 0) { continue; } childComponent.setStyle(n, styleValues[index % styleValues.length]) } } /** * @private */ protected function defaultDataTipFunction(item:Object, index:int, series:ISeries):String { if(series.displayName) { return series.displayName; } return ""; } /** * @private * Passes data to the data tip. */ protected function refreshDataTip():void { var item:Object = this._lastDataTipRenderer.data; var series:ISeries = this._lastDataTipRenderer.series; var index:int = series.itemRendererToIndex(this._lastDataTipRenderer); var dataTipText:String = ""; if(this.dataTipFunction != null) { dataTipText = this.dataTipFunction(item, index, series); } var dataTipRenderer:IDataTipRenderer = this.dataTip as IDataTipRenderer; dataTipRenderer.text = dataTipText; dataTipRenderer.data = item; this.setChildIndex(this.dataTip, this.numChildren - 1); if(this.dataTip is UIComponent) { UIComponent(this.dataTip).drawNow(); } } //-------------------------------------- // Protected Event Handlers //-------------------------------------- /** * @private * Display the data tip when the user moves the mouse over a chart marker. */ protected function chartItemRollOver(event:ChartEvent):void { this._lastDataTipRenderer = event.itemRenderer; this.refreshDataTip(); var position:Point = this.mousePositionToDataTipPosition(); this.dataTip.x = position.x; this.dataTip.y = position.y; this.dataTip.visible = true; this.stage.addEventListener(MouseEvent.MOUSE_MOVE, stageMouseMoveHandler, false, 0 ,true); } /** * @private * Hide the data tip when the user moves the mouse off a chart marker. */ protected function chartItemRollOut(event:ChartEvent):void { this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, stageMouseMoveHandler); this.dataTip.visible = false; } //-------------------------------------- // Private Methods //-------------------------------------- /** * @private * Determines the position for the data tip based on the mouse position * and the bounds of the chart. Attempts to keep the data tip within the * chart bounds so that it isn't hidden by any other display objects. */ private function mousePositionToDataTipPosition():Point { var position:Point = new Point(); position.x = this.mouseX + 2; position.x = Math.min(this.width - this.dataTip.width, position.x); position.y = this.mouseY - this.dataTip.height - 2; position.y = Math.max(0, position.y); return position; } //-------------------------------------- // Private Event Handlers //-------------------------------------- /** * @private * The plot area needs to redraw the axes if series data changes. */ private function seriesDataChangeHandler(event:Event):void { this.invalidate(InvalidationType.DATA); if(this.dataTip.visible) { this.refreshDataTip(); } } /** * @private * Make the data tip follow the mouse. */ private function stageMouseMoveHandler(event:MouseEvent):void { var position:Point = this.mousePositionToDataTipPosition(); this.dataTip.x = position.x; this.dataTip.y = position.y; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -