返回 导航

Flex

hangge.com

Flex4 - 给LineChart线图添加拖动放大功能

作者:hangge | 2015-09-22 09:15
有时候线图或面积图里数据太密集,如果想要重点关注,或者看清其中某一段时间的数据趋势。就需要给图表添加一个动态缩放功能。
即允许鼠标在图上拖动选择一个区域,图表便自动放大展示这块区域的内容。同时放大后右上角还会出现一个“还原”按钮,点击恢复成最初状态。

效果图如下:




代码如下:
<?xml version="1.0"?>
<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"
			   creationComplete="init(event)">
	<fx:Script>
		<![CDATA[
			import mx.charts.chartClasses.Series;
			import mx.collections.ArrayCollection;
			import mx.events.FlexEvent;
			
			//原始数据
			private var _myData:ArrayCollection = new ArrayCollection( [
				{time: "10:00", value1: 34, value2: 54},
				{time: "10:05", value1: 35, value2: 65},
				{time: "10:10", value1: 25, value2: 34},
				{time: "10:15", value1: 36, value2: 56},
				{time: "10:20", value1: 54, value2: 45},
				{time: "10:25", value1: 63, value2: 66},
				{time: "10:30", value1: 23, value2: 34},
				{time: "10:35", value1: 55, value2: 73},
				{time: "10:40", value1: 64, value2: 44},
				{time: "10:45", value1: 75, value2: 23},
				{time: "10:50", value1: 31, value2: 56},
				{time: "10:55", value1: 33, value2: 43},
				{time: "11:00", value1: 34, value2: 55},
				{time: "11:05", value1: 23, value2: 23},
				{time: "11:10", value1: 25, value2: 34},
				{time: "11:15", value1: 23, value2: 56},
				{time: "11:20", value1: 54, value2: 45},
				{time: "11:25", value1: 63, value2: 43},
				{time: "11:30", value1: 34, value2: 32},
				{time: "11:35", value1: 33, value2: 43},
				{time: "11:40", value1: 54, value2: 15},
				{time: "11:45", value1: 75, value2: 23},
				{time: "11:50", value1: 13, value2: 43},
				{time: "11:55", value1: 33, value2: 32},
				{time: "12:00", value1: 34, value2: 54},
				{time: "12:05", value1: 35, value2: 65},
				{time: "12:10", value1: 25, value2: 34},
				{time: "12:15", value1: 32, value2: 56},
				{time: "12:20", value1: 54, value2: 45},
				{time: "12:25", value1: 63, value2: 66},
				{time: "12:30", value1: 53, value2: 34},
				{time: "12:35", value1: 55, value2: 43},
				{time: "12:40", value1: 64, value2: 33},
				{time: "12:45", value1: 75, value2: 23},
				{time: "12:50", value1: 31, value2: 56},
				{time: "12:55", value1: 23, value2: 43},
				{time: "13:00", value1: 45, value2: 52},
				{time: "13:05", value1: 34, value2: 34},
				{time: "13:10", value1: 25, value2: 34},
				{time: "13:15", value1: 23, value2: 56},
				{time: "13:20", value1: 54, value2: 43},
				{time: "13:25", value1: 63, value2: 43},
				{time: "13:30", value1: 44, value2: 55},
				{time: "13:35", value1: 33, value2: 43},
				{time: "13:40", value1: 54, value2: 23},
				{time: "13:45", value1: 75, value2: 23},
				{time: "13:50", value1: 13, value2: 55},
				{time: "13:55", value1: 33, value2: 32}
			]);
			
			//放大区域的开始时间
			private var _zoomStartTime:String="";
			//放大区域的结束时间
			private var _zoomEndTime:String="";
			//放大区域的开始索引
			private var _zoomStartIndex:int=-1;
			//放大区域的结束索引
			private var _zoomEndIndex:int=-1;
			
			//页面初始化
			protected function init(event:FlexEvent):void
			{
				vAxis.maximum = 100;
				loadData();
			}
			
			//数据加载
			private function loadData():void{
				linechart.dataProvider = _myData;
				zoomOutBtn.visible = false;
			}
			
			//鼠标按下
			protected function linechart_mouseDownHandler(event:MouseEvent):void
			{
				//记下鼠标按下时的时间和位置
				_zoomStartTime = getTimeNearMouse();
				for(var index:int = 0;index<linechart.dataProvider.length;index++){
					if(linechart.dataProvider.getItemAt(index).time == _zoomStartTime){
						_zoomStartIndex = index;
						break;
					}
				}
			}
			
			//鼠标移动
			private function linechart_mouseMoveHandler(event:MouseEvent):void {
				if(_zoomStartTime != ""){
					//记下鼠标移动时的时间和位置
					_zoomEndTime = getTimeNearMouse();
					for(var index:int = 0;index<linechart.dataProvider.length;index++){
						if(linechart.dataProvider.getItemAt(index).time == _zoomEndTime){
							_zoomEndIndex = index;
							break;
						}
					}
					
					//绘制 选中区域背景 
					var startX:Number = linechart.series[0].items[_zoomStartIndex]["x"];
					var endX:Number = linechart.series[0].items[_zoomEndIndex]["x"];;
					zoomArea.graphics.clear();
					zoomArea.graphics.beginFill(0x65EEFC,0.4);
					zoomArea.graphics.drawRect(startX,0,endX-startX,chartBg.height);
					zoomArea.graphics.endFill();
				}
			}
			
			//鼠标弹起
			protected function linechart_mouseUpHandler(event:MouseEvent):void
			{
				if(_zoomStartTime!=""){
					zoomIn()
				}
				
				_zoomStartTime = "";
			}
			
			//开始缩放
			private function zoomIn():void{
				zoomArea.graphics.clear();
				
				//避免单击也放大
				if(_zoomStartTime == _zoomEndTime){
					return;
				}
				
				zoomOutBtn.visible = true;
				
				//保证开始索引小于结束索引(不管鼠标从左向右拖 还是从右向左拖)
				if(_zoomStartIndex>_zoomEndIndex){
					var t:int = _zoomStartIndex;
					_zoomStartIndex = _zoomEndIndex;
					_zoomEndIndex = t;
				}
				
				//只加载选中区域的数据
				var zoomData:ArrayCollection = new ArrayCollection();
				for(var index:int = 0;index<linechart.dataProvider.length;index++){
					if(index<=_zoomEndIndex && index >=_zoomStartIndex){
						zoomData.addItem(linechart.dataProvider.getItemAt(index));
					}
				}
				linechart.dataProvider = zoomData;
			}
			
			//获取最接近鼠标位置的时间
			private function getTimeNearMouse():String{
				if(linechart.series[0]!=null){
					var series:Series = linechart.series[0];
					var leftPoint:Point = new Point(series.mouseX,0);
					var leftArr:Array = series.localToData(leftPoint);	
					return leftArr[0];
				}else{
					return "";
				}
			}
			
		]]>
	</fx:Script>
	
	<fx:Declarations>
		<!-- 轴线样式 (暂时不需要,改成背景上绘制)-->
		<mx:SolidColorStroke id = "axisS1" color="0xE3E3E3" weight="1" alpha="0"/>
	</fx:Declarations>
	
	<s:Group id="chartGroup" width="60%" height="60%" verticalCenter="0" horizontalCenter="0">	
		<mx:LineChart id="linechart" top="10" bottom="0" width="100%" seriesFilters="[]"
					  fontSize="12" color="0x707070" showDataTips="true"
					  mouseMove="linechart_mouseMoveHandler(event)" 
					  mouseDown="linechart_mouseDownHandler(event)" 
					  mouseUp="linechart_mouseUpHandler(event)"
					  rollOut="linechart_mouseUpHandler(event)">
			<mx:backgroundElements>
				<s:Group width="100%" height="100%" id="chartBg">
					<s:Rect left="0" right="1" top="0" bottom="0">
						<s:fill>
							<s:SolidColor alpha="1" color="#F5F5F5"/>
						</s:fill>  
						<s:stroke>
							<s:SolidColorStroke color="0xE3E3E3" weight="1"/>
						</s:stroke>
					</s:Rect>   
					<s:Group  width="100%" height="100%" id="zoomArea">
						<!-- 在此绘制选中区域 -->
					</s:Group>	
				</s:Group>
				<mx:GridLines gridDirection="both" >
					<mx:horizontalStroke>
						<mx:SolidColorStroke  color="0xE3E3E3" weight="1"/>
					</mx:horizontalStroke>
					<mx:verticalStroke>
						<mx:SolidColorStroke  color="0xEAEAEA" weight="1"/>
					</mx:verticalStroke>
				</mx:GridLines>    
				<s:Group width="100%" height="100%">
					<s:Button id="zoomOutBtn" label="还原" right="0" click="loadData()"
							  visible="false"/>
				</s:Group>
			</mx:backgroundElements>
			<mx:horizontalAxis>
				<mx:CategoryAxis id="hAxis" categoryField="time"/>
			</mx:horizontalAxis>
			<mx:horizontalAxisRenderers>
				<mx:AxisRenderer axis="{hAxis}" tickPlacement="none" minorTickPlacement="none"
								 axisStroke="{axisS1}" canDropLabels="true"/>
			</mx:horizontalAxisRenderers>
			<mx:verticalAxis>
				<mx:LinearAxis id="vAxis"/>
			</mx:verticalAxis>
			<mx:verticalAxisRenderers>
				<mx:AxisRenderer axis="{vAxis}" tickPlacement="none" minorTickPlacement="none"
								 axisStroke="{axisS1}"/>
			</mx:verticalAxisRenderers>
			<mx:series>
				<mx:LineSeries  id="line1" yField="value1" form="segment" displayName="数量1">
					<mx:lineStroke>
						<mx:SolidColorStroke color="0x008EFF" weight="2"/>
					</mx:lineStroke>
				</mx:LineSeries>
				<mx:LineSeries  id="line2" yField="value2" form="segment" displayName="数量2">
					<mx:lineStroke>
						<mx:SolidColorStroke color="0x1ACE4D" weight="2"/>
					</mx:lineStroke>
				</mx:LineSeries>
			</mx:series>
		</mx:LineChart>
	</s:Group>
</s:Application>
评论

全部评论(0)

回到顶部