Flex4 - 给图表添加一条跟随鼠标辅助竖线,并显示竖线下所有点的tip
1,需要实现的功能:

4,下面再做一个功能改进
以线图为例,想要在图表上添加一条辅助线(标记线),位置会根据鼠标移动到最近的数据点上。同时把这条辅助线位置上所有数据点的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>