返回 导航

Flex

hangge.com

Flex4 - 给图表添加一条跟随鼠标辅助竖线,并显示竖线下所有点的tip

作者:hangge | 2015-08-23 12:00
1,需要实现的功能:
以线图为例,想要在图表上添加一条辅助线(标记线),位置会根据鼠标移动到最近的数据点上。同时把这条辅助线位置上所有数据点的tip提示显示出来。


2,实现原理:
(1)监听mouseMove事件,判断距鼠标x坐标最近的数据点。
(2)获取数据点的索引,将所有图形序列里同一索引(同一类别刻度)下的数据点的提示都显示,其他点的不显示。

3,代码如下:
<?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.ChartItem;
			import mx.charts.chartClasses.Series;
			import mx.collections.ArrayCollection;
			import mx.core.UIComponent;
			import mx.events.FlexEvent;
			
			//鼠标辅助线
			private var _cursorMarker:UIComponent;
			
			private var _myData:ArrayCollection = new ArrayCollection( [
				{ month: "18:00", value: 20, value2: 24, value3: 28},
				{ month: "19:00", value: 60, value2: 70, value3: 65},
				{ month: "20:00", value: 215, value2: 100, value3: 150},
				{ month: "21:00", value: 202, value2: 150, value3: 120},
				{ month: "22:00", value: 190, value2: 60, value3: 100},
				{ month: "23:00", value: 95, value2: 50, value3: 28}]);
			
			protected function init(event:FlexEvent):void
			{
				//初始化鼠标辅助线
				_cursorMarker = new UIComponent();
				chartBg.addElement(_cursorMarker);
				
				loadData();
			}
			
			private function loadData():void{
				//每次数据加载前先把显示所有提示给去除(要不然重新加载数据时会卡)
				linechart.showAllDataTips =false;
				
				linechart.dataProvider = _myData;
			}
			
			private function dataTipHandler(event:MouseEvent):void {
				//做个保护判断是否有图形序列
				if(linechart.series.length==0){
					return;
				}
				
				var leftPoint:Point = new Point(linechart.mouseX,0);           
				
				var series:Series = linechart.series[0];
				var item:ChartItem;
				
				//获取最x坐标接近的数据点的索引 index
				var leftArr:Array = series.localToData(leftPoint);
				var index:int;
				for(index = 0;index<linechart.dataProvider.length;index++){
					if(linechart.dataProvider.getItemAt(index).month == leftArr[0]){
						break;
					}
				}
				
				//遍历所有序列,把同一类别刻度下的tip都显示出来,其他不显示           
				for each(var s:Series in linechart.series){
					s.dataTipItems = [];
					series = s;
					item = series.items[index];
					if(item != null)
						series.dataTipItems.push(item);
				}
				
				//使用callLater避免首次加载时,如果数据多的话,提示要卡个半天
				callLater(function():void{linechart.showAllDataTips = true;});
				//linechart.showAllDataTips = true;
				
				if(item != null){
					//var globalPoint:Point = series.localToGlobal(new Point(item["x"],item["y"]));
					//_cursorMarker.x = linechart.globalToContent((new Point(item["x"],item["y"])).).x;
					_cursorMarker.x =  item["x"];
					_cursorMarker.graphics.clear();
					_cursorMarker.graphics.lineStyle(2, 0xff0000, .55);
					_cursorMarker.graphics.moveTo(0,0);
					_cursorMarker.graphics.lineTo(0,_cursorMarker.parent.height);
				}
			}
		]]>
	</fx:Script>
	
	<fx:Declarations>
		<!-- 轴线样式 (暂时不需要,改成背景上绘制)-->
		<mx:SolidColorStroke id = "axisS1" color="0xE3E3E3" weight="1" alpha="0"/>
	</fx:Declarations>
	
	<mx:LineChart id="linechart" height="60%" width="60%" seriesFilters="[]"
				  verticalCenter="0" horizontalCenter="0" fontSize="12" color="0x707070"
				  showDataTips="false"
				  mouseMove="dataTipHandler(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>
			<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>          
		</mx:backgroundElements>
		<mx:horizontalAxis>
			<mx:CategoryAxis id="hAxis" categoryField="month"/>
		</mx:horizontalAxis>
		<mx:horizontalAxisRenderers>
			<mx:AxisRenderer axis="{hAxis}" tickPlacement="none" minorTickPlacement="none"
							 axisStroke="{axisS1}"/>
		</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="value" 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:LineSeries  id="line3" yField="value3" form="segment" displayName="数量3">
				<mx:lineStroke>
					<mx:SolidColorStroke color="0xE07511" weight="2"/>
				</mx:lineStroke>
			</mx:LineSeries>
		</mx:series>
	</mx:LineChart>
</s:Application>

4,下面再做一个功能改进
由于同一竖线下的时间都一样,我们可把提示时间提出了放到图表外的文本标签中,并跟随红线移动。

<?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.ChartItem;
			import mx.charts.HitData;
			import mx.charts.chartClasses.Series;
			import mx.collections.ArrayCollection;
			import mx.core.UIComponent;
			import mx.events.FlexEvent;
			
			//鼠标辅助线
			private var _cursorMarker:UIComponent;
			
			private var _myData:ArrayCollection = new ArrayCollection( [
				{ month: "18:00", value: 20, value2: 24, value3: 28},
				{ month: "19:00", value: 60, value2: 70, value3: 65},
				{ month: "20:00", value: 215, value2: 100, value3: 150},
				{ month: "21:00", value: 202, value2: 150, value3: 120},
				{ month: "22:00", value: 190, value2: 60, value3: 100},
				{ month: "23:00", value: 95, value2: 50, value3: 28}]);
			
			protected function init(event:FlexEvent):void
			{
				//初始化鼠标辅助线
				_cursorMarker = new UIComponent();
				chartBg.addElement(_cursorMarker);
				
				loadData();
			}
			
			private function loadData():void{
				//每次数据加载前先把显示所有提示给去除(要不然重新加载数据时会卡)
				linechart.showAllDataTips =false;
				
				linechart.dataProvider = _myData;
			}
			
			private function dataTipHandler(event:MouseEvent):void {
				//做个保护判断是否有图形序列
				if(linechart.series.length==0){
					return;
				}
				
				var leftPoint:Point = new Point(linechart.mouseX,0);          
				
				var series:Series = linechart.series[0];
				var item:ChartItem;
				
				//获取最x坐标接近的数据点的索引 index
				var leftArr:Array = series.localToData(leftPoint);
				var index:int;
				for(index = 0;index<linechart.dataProvider.length;index++){
					if(linechart.dataProvider.getItemAt(index).month == leftArr[0]){
						break;
					}
				}
				
				//遍历所有序列,把同一类别刻度下的tip都显示出来,其他不显示          
				for each(var s:Series in linechart.series){
					s.dataTipItems = [];
					series = s;
					item = series.items[index];
					if(item != null)
						series.dataTipItems.push(item);
				}
				
				//使用callLater避免首次加载时,如果数据多的话,提示要卡个半天
				callLater(function():void{linechart.showAllDataTips = true;});
				//linechart.showAllDataTips = true;
				
				if(item != null){
					//var globalPoint:Point = series.localToGlobal(new Point(item["x"],item["y"]));
					//_cursorMarker.x = linechart.globalToContent((new Point(item["x"],item["y"])).).x;
					_cursorMarker.x =  item["x"];
					_cursorMarker.graphics.clear();
					_cursorMarker.graphics.lineStyle(2, 0xff0000, .55);
					_cursorMarker.graphics.moveTo(0,0);
					_cursorMarker.graphics.lineTo(0,_cursorMarker.parent.height);
					
					//时间标齐赋值与移动
					var _p:Point = chartBg.localToGlobal(new Point(item["x"],0));
					_p = chartGroup.globalToContent(_p);
					timeLab.text = leftArr[0];
					timeLab.x = _p.x - timeLab.width/2;
				}
			}
			
			private function dataTips(e:HitData):String{
				var s:String= LineSeries(e.element).displayName+":"+e.chartItem["yValue"];
				return s; 
			}
		]]>
	</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="false" dataTipFunction="dataTips"
					  mouseMove="dataTipHandler(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>
				<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>         
			</mx:backgroundElements>
			<mx:horizontalAxis>
				<mx:CategoryAxis id="hAxis" categoryField="month"/>
			</mx:horizontalAxis>
			<mx:horizontalAxisRenderers>
				<mx:AxisRenderer axis="{hAxis}" tickPlacement="none" minorTickPlacement="none"
								 axisStroke="{axisS1}"/>
			</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="value" 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:LineSeries  id="line3" yField="value3" form="segment" displayName="数量3">
					<mx:lineStroke>
						<mx:SolidColorStroke color="0xE07511" weight="2"/>
					</mx:lineStroke>
				</mx:LineSeries>
			</mx:series>
		</mx:LineChart>
		<s:Label id="timeLab"/>
	</s:Group>
</s:Application>
评论

全部评论(0)

回到顶部