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)