Flex4 - 给图表添加一条跟随鼠标辅助竖线,并显示竖线下所有点的tip
作者:hangge | 2015-08-23 12:00
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>
全部评论(0)