3Dchart理解
想在Flex Chart中为图例设置3D效果,近几天查找了些资料,动手做了个DEMO供大家参考!
DEMO演示地址http://xingjunli.webs.com/flash/flexChartDemo.swf,先来个图片看看最终效果:
相关知识点
1、图表使用的我就不多做介绍了,网上也很多官方也有不错的教程(参考:Skinning ChartItem objects );
2、要自定义图表Series,我们要做的就是重写ProgrammaticSkin基类并实现IDataRenderer接口方法中的updateDisplayList方法,在Series中应用我们自定义的外观类“drawhelper.histogramSkin”就好了如:
[xhtml] view plaincopyprint?
<mx:ColumnSeries showDataEffect="slideIn" hideDataEffect="slideOut" xField="label" yField="value" itemRenderer="drawhelper.histogramSkin" />
<mx:ColumnSeries showDataEffect="slideIn" hideDataEffect="slideOut" xField="label" yField="value" itemRenderer="drawhelper.histogramSkin" />
3、我们这里使用Graphic在2D场景中绘制(3D)立方体的方式绘制Series,先理解应用3D坐标(在Series中绘制是从下向上绘制的所你看到的绘制过程中坐标系刚好是倒转过来的)如图:
实现过程及代码:
1、自定义立方图外观类:
[xhtml] view plaincopyprint?
package drawhelper
{
import flash.geom.Point;
import mx.charts.series.items.ColumnSeriesItem;
import mx.core.IDataRenderer;
import mx.skins.ProgrammaticSkin;
public class solidSkin extends ProgrammaticSkin implements IDataRenderer
{
private var colors:Array = [0x60cb00,0x6a7a88,0x3698ff,0x66a800,0xff6600,0x655fc8,0xd2691e];
private var _chartItem:ColumnSeriesItem;
public function solidSkin()
{
super();
}
public function get data():Object
{
return Object(_chartItem);
}
public function set data(value:Object):void
{
_chartItem = value as ColumnSeriesItem;
invalidateDisplayList();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth,unscaledHeight);
this.graphics.clear();
var points:Array = getPoints(unscaledWidth*0.65,unscaledHeight);
drawFill(points[4],points[7],points[6],points[5]);
drawFill(points[6],points[2],points[3],points[7]);
drawFill(points[7],points[4],points[0],points[3]);
this.graphics.endFill();
}
//根据长宽获取3D坐标信息
function getPoints(w:Number,h:Number):Array
{
var points:Array = new Array(8);
points[0] = new Point(0,h);
points[1] = new Point(w,h);
points[2] = new Point(w,0);
points[3] = new Point(0,0);
points[4] = new Point(0+w/2.0,h+w/2.0);
points[5] = new Point(w+w/2.0,h+w/2.0);
points[6] = new Point(w+w/2.0,0+w/2.0);
points[7] = new Point(0+w/2.0,0+w/2.0);
return points;
}
//根据传入的坐标信息,绘制线条及填充绘制区域
function drawFill(...args):void
{
with(this.graphics)
{
lineStyle(0.5,0x7DBFC6,0.8);
beginFill(colors[(_chartItem == null)?0:_chartItem.index],0.95);
moveTo(args[0].x,args[0].y);
for(var i=1;i<args.length;i++)
{
lineTo(args[i].x,args[i].y);
}
}
}
}
}
package drawhelper
{
import flash.geom.Point;
import mx.charts.series.items.ColumnSeriesItem;
import mx.core.IDataRenderer;
import mx.skins.ProgrammaticSkin;
public class solidSkin extends ProgrammaticSkin implements IDataRenderer
{
private var colors:Array = [0x60cb00,0x6a7a88,0x3698ff,0x66a800,0xff6600,0x655fc8,0xd2691e];
private var _chartItem:ColumnSeriesItem;
public function solidSkin()
{
super();
}
public function get data():Object
{
return Object(_chartItem);
}
public function set data(value:Object):void
{
_chartItem = value as ColumnSeriesItem;
invalidateDisplayList();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth,unscaledHeight);
this.graphics.clear();
var points:Array = getPoints(unscaledWidth*0.65,unscaledHeight);
drawFill(points[4],points[7],points[6],points[5]);
drawFill(points[6],points[2],points[3],points[7]);
drawFill(points[7],points[4],points[0],points[3]);
this.graphics.endFill();
}
//根据长宽获取3D坐标信息
function getPoints(w:Number,h:Number):Array
{
var points:Array = new Array(8);
points[0] = new Point(0,h);
points[1] = new Point(w,h);
points[2] = new Point(w,0);
points[3] = new Point(0,0);
points[4] = new Point(0+w/2.0,h+w/2.0);
points[5] = new Point(w+w/2.0,h+w/2.0);
points[6] = new Point(w+w/2.0,0+w/2.0);
points[7] = new Point(0+w/2.0,0+w/2.0);
return points;
}
//根据传入的坐标信息,绘制线条及填充绘制区域
function drawFill(...args):void
{
with(this.graphics)
{
lineStyle(0.5,0x7DBFC6,0.8);
beginFill(colors[(_chartItem == null)?0:_chartItem.index],0.95);
moveTo(args[0].x,args[0].y);
for(var i=1;i<args.length;i++)
{
lineTo(args[i].x,args[i].y);
}
}
}
}
}
2、自定义圆柱图外观类:
[c-sharp] view plaincopyprint?
package drawhelper
{
import flash.display.Graphics;
import flash.display.GradientType;
import mx.charts.series.items.ColumnSeriesItem;
import mx.core.IDataRenderer;
import mx.skins.ProgrammaticSkin;
public class histogramSkin extends ProgrammaticSkin implements IDataRenderer
{
private var colors:Array = [0x60cb00,0x6a7a88,0x3698ff,0x66a800,0xff6600,0x655fc8,0xd2691e];
private var _chartItem:ColumnSeriesItem;
public function histogramSkin(){}
public function get data():Object
{
return Object(_chartItem);
}
public function set data(value:Object):void
{
_chartItem = value as ColumnSeriesItem;
invalidateDisplayList();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth,unscaledHeight);
var g:Graphics = graphics;
g.clear();
g.beginFill(colors[(_chartItem == null)?0:_chartItem.index]);
g.drawRect(0,unscaledWidth * 0.125,unscaledWidth,unscaledHeight);
g.lineStyle(1,0xffffff,0.25);
g.beginFill(colors[(_chartItem == null)?0:_chartItem.index]);
g.drawEllipse(0,0,unscaledWidth,unscaledWidth * 0.25);
g.endFill();
}
}
}
package drawhelper
{
import flash.display.Graphics;
import flash.display.GradientType;
import mx.charts.series.items.ColumnSeriesItem;
import mx.core.IDataRenderer;
import mx.skins.ProgrammaticSkin;
public class histogramSkin extends ProgrammaticSkin implements IDataRenderer
{
private var colors:Array = [0x60cb00,0x6a7a88,0x3698ff,0x66a800,0xff6600,0x655fc8,0xd2691e];
private var _chartItem:ColumnSeriesItem;
public function histogramSkin(){}
public function get data():Object
{
return Object(_chartItem);
}
public function set data(value:Object):void
{
_chartItem = value as ColumnSeriesItem;
invalidateDisplayList();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth,unscaledHeight);
var g:Graphics = graphics;
g.clear();
g.beginFill(colors[(_chartItem == null)?0:_chartItem.index]);
g.drawRect(0,unscaledWidth * 0.125,unscaledWidth,unscaledHeight);
g.lineStyle(1,0xffffff,0.25);
g.beginFill(colors[(_chartItem == null)?0:_chartItem.index]);
g.drawEllipse(0,0,unscaledWidth,unscaledWidth * 0.25);
g.endFill();
}
}
}
3、实现立方图组件
[xhtml] view plaincopyprint?
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel title="{Title}" xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%">
<mx:Script>
<!--[CDATA[
import mx.charts.chartClasses.CartesianCanvasValue;
import mx.graphics.codec.JPEGEncoder;
import mx.collections.ArrayCollection;
import drawhelper.histogramSkin;
[Bindable]
public var expenses:ArrayCollection;
[Bindable]
private var lengValue:String;
[Bindable]
private var Title:String;
[Bindable]
private var xLabel:String;
[Bindable]
private var isShowAllTrip:Boolean =false;
public function init(datas:ArrayCollection,leng:String,title:String,xtitle:String="",showAllTrip:Boolean=false):void
{
isShowAllTrip = showAllTrip;
Title = title;
xLabel= xtitle;
if(expenses != null && expenses.length>0)
{
expenses.removeAll();
}
else
{
expenses = new ArrayCollection();
}
expenses = datas;
lengValue = leng;
}
]]-->
</mx:Script>
<mx:SeriesSlide id="slideIn" duration="600" direction="up"/>
<mx:SeriesSlide id="slideOut" duration="200" direction="down"/>
<mx:ColumnChart horizontalCenter="true" fontSize="13.5" id="myChart" dataProvider="{expenses}"
showDataTips="{!isShowAllTrip}" textAlign="center" width="95%" height="100%" showAllDataTips="{isShowAllTrip}">
<mx:seriesFilters>
<mx:Array/>
</mx:seriesFilters>
<mx:horizontalAxis>
<mx:CategoryAxis dataProvider="{expenses}" categoryField="label" />
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries showDataEffect="slideIn" hideDataEffect="slideOut" xField="label" yField="value" itemRenderer="drawhelper.solidSkin" />
</mx:series>
</mx:ColumnChart>
<mx:Label id="xMsg" text="{xLabel}" fontSize="14" width="95%" textAlign="center" letterSpacing="1.5">
</mx:Label>
<mx:Legend id="lenged" x="{parent.width - lenged.width - 50}" y="5" visible="{(lengValue != '')}">
<mx:LegendItem label="{lengValue}" styleName="legendItem" />
</mx:Legend>
</mx:Panel>
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel title="{Title}" xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%">
<mx:Script>
<!--[CDATA[
import mx.charts.chartClasses.CartesianCanvasValue;
import mx.graphics.codec.JPEGEncoder;
import mx.collections.ArrayCollection;
import drawhelper.histogramSkin;
[Bindable]
public var expenses:ArrayCollection;
[Bindable]
private var lengValue:String;
[Bindable]
private var Title:String;
[Bindable]
private var xLabel:String;
[Bindable]
private var isShowAllTrip:Boolean =false;
public function init(datas:ArrayCollection,leng:String,title:String,xtitle:String="",showAllTrip:Boolean=false):void
{
isShowAllTrip = showAllTrip;
Title = title;
xLabel= xtitle;
if(expenses != null && expenses.length>0)
{
expenses.removeAll();
}
else
{
expenses = new ArrayCollection();
}
expenses = datas;
lengValue = leng;
}
]]-->
</mx:Script>
<mx:SeriesSlide id="slideIn" duration="600" direction="up"/>
<mx:SeriesSlide id="slideOut" duration="200" direction="down"/>
<mx:ColumnChart horizontalCenter="true" fontSize="13.5" id="myChart" dataProvider="{expenses}"
showDataTips="{!isShowAllTrip}" textAlign="center" width="95%" height="100%" showAllDataTips="{isShowAllTrip}">
<mx:seriesFilters>
<mx:Array/>
</mx:seriesFilters>
<mx:horizontalAxis>
<mx:CategoryAxis dataProvider="{expenses}" categoryField="label" />
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries showDataEffect="slideIn" hideDataEffect="slideOut" xField="label" yField="value" itemRenderer="drawhelper.solidSkin" />
</mx:series>
</mx:ColumnChart>
<mx:Label id="xMsg" text="{xLabel}" fontSize="14" width="95%" textAlign="center" letterSpacing="1.5">
</mx:Label>
<mx:Legend id="lenged" x="{parent.width - lenged.width - 50}" y="5" visible="{(lengValue != '')}">
<mx:LegendItem label="{lengValue}" styleName="legendItem" />
</mx:Legend>
</mx:Panel>
4、实现柱状图组件
[xhtml] view plaincopyprint?
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel title="{Title}" xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%">
<mx:Script>
<!--[CDATA[
import mx.charts.chartClasses.CartesianCanvasValue;
import mx.graphics.codec.JPEGEncoder;
import mx.collections.ArrayCollection;
import drawhelper.histogramSkin;
[Bindable]
public var expenses:ArrayCollection;
[Bindable]
private var lengValue:String;
[Bindable]
private var Title:String;
[Bindable]
private var xLabel:String;
[Bindable]
private var isShowAllTrip:Boolean =false;
public function init(datas:ArrayCollection,leng:String,title:String,xtitle:String="",showAllTrip:Boolean=false):void
{
isShowAllTrip = showAllTrip;
Title = title;
xLabel= xtitle;
if(expenses != null && expenses.length>0)
{
expenses.removeAll();
}
else
{
expenses = new ArrayCollection();
}
expenses = datas;
lengValue = leng;
}
]]-->
</mx:Script>
<mx:SeriesSlide id="slideIn" duration="600" direction="up"/>
<mx:SeriesSlide id="slideOut" duration="200" direction="down"/>
<mx:ColumnChart horizontalCenter="true" fontSize="13.5" id="myChart" dataProvider="{expenses}"
showDataTips="{!isShowAllTrip}" textAlign="center" width="95%" height="100%" showAllDataTips="{isShowAllTrip}">
<mx:seriesFilters>
<mx:Array/>
</mx:seriesFilters>
<mx:horizontalAxis>
<mx:CategoryAxis dataProvider="{expenses}" categoryField="label" />
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries showDataEffect="slideIn" hideDataEffect="slideOut" xField="label" yField="value" itemRenderer="drawhelper.histogramSkin" />
</mx:series>
</mx:ColumnChart>
<mx:Label id="xMsg" text="{xLabel}" fontSize="14" width="95%" textAlign="center" letterSpacing="1.5">
</mx:Label>
<mx:Legend id="lenged" x="{parent.width - lenged.width - 50}" y="5" visible="{(lengValue != '')}">
<mx:LegendItem label="{lengValue}" styleName="legendItem" />
</mx:Legend>
</mx:Panel>
<?xml version="1.0" encoding="utf-8"?>
<mx:Panel title="{Title}" xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%">
<mx:Script>
<!--[CDATA[
import mx.charts.chartClasses.CartesianCanvasValue;
import mx.graphics.codec.JPEGEncoder;
import mx.collections.ArrayCollection;
import drawhelper.histogramSkin;
[Bindable]
public var expenses:ArrayCollection;
[Bindable]
private var lengValue:String;
[Bindable]
private var Title:String;
[Bindable]
private var xLabel:String;
[Bindable]
private var isShowAllTrip:Boolean =false;
public function init(datas:ArrayCollection,leng:String,title:String,xtitle:String="",showAllTrip:Boolean=false):void
{
isShowAllTrip = showAllTrip;
Title = title;
xLabel= xtitle;
if(expenses != null && expenses.length>0)
{
expenses.removeAll();
}
else
{
expenses = new ArrayCollection();
}
expenses = datas;
lengValue = leng;
}
]]-->
</mx:Script>
<mx:SeriesSlide id="slideIn" duration="600" direction="up"/>
<mx:SeriesSlide id="slideOut" duration="200" direction="down"/>
<mx:ColumnChart horizontalCenter="true" fontSize="13.5" id="myChart" dataProvider="{expenses}"
showDataTips="{!isShowAllTrip}" textAlign="center" width="95%" height="100%" showAllDataTips="{isShowAllTrip}">
<mx:seriesFilters>
<mx:Array/>
</mx:seriesFilters>
<mx:horizontalAxis>
<mx:CategoryAxis dataProvider="{expenses}" categoryField="label" />
</mx:horizontalAxis>
<mx:series>
<mx:ColumnSeries showDataEffect="slideIn" hideDataEffect="slideOut" xField="label" yField="value" itemRenderer="drawhelper.histogramSkin" />
</mx:series>
</mx:ColumnChart>
<mx:Label id="xMsg" text="{xLabel}" fontSize="14" width="95%" textAlign="center" letterSpacing="1.5">
</mx:Label>
<mx:Legend id="lenged" x="{parent.width - lenged.width - 50}" y="5" visible="{(lengValue != '')}">
<mx:LegendItem label="{lengValue}" styleName="legendItem" />
</mx:Legend>
</mx:Panel>
5、传入数据,绑定组件完成图表
[xhtml] view plaincopyprint?
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" width="800" height="300" layout="absolute" creationComplete="init()"
xmlns:chart="component.chart.*">
<mx:Style>
/* CSS file */
Application
{
backgroundColor:#eef1f4;
}
Panel
{
borderStyle: solid;
borderColor: #dbe2e8;
borderThickness: 2;
roundedBottomCorners: false;
cornerRadius: 1;
headerHeight: 27;
backgroundAlpha: 1;
dropShadowEnabled: true;
shadowDistance: 1;
shadowDirection: center;
titleStyleName: "mypanelTitle";
}
.mypanelTitle
{
letterSpacing: 1;
textAlign: center;
fontSize: 14;
}
.legendItem
{
fontSize:14;
color:#577ba1;
fontFamily: Arial;
fill:#577ba1;
fontWeight: normal;
}
.legendItemArea
{
fontSize:14;
fontFamily: Arial;
}
ProgressBar {
borderColor: #cccccc;
barColor: #8ec0e2;
trackColors: #eae8e8, #efeeec;
color: #000000;
paddingLeft: 6;
paddingRight: 5;
textIndent: 0;
letterSpacing: 1;
trackHeight: 20;
verticalGap: 5;
fontFamily: Arial;
fontSize: 10;
fontWeight: bold;
}
</mx:Style>
<mx:Script>
<!--[CDATA[
import mx.collections.ArrayCollection;
function init():void
{
boundChart(
{data:[25,36,77,65,25,35],date:[2003,2004,2005,2006,2007,2008],date_format:"m.d",title:"自定义图例样式",xtitle:"ProgrammaticSkin Demo"},
"统计图例"
);
}
/*
* cData: 图片数据
* cleng: 页脚
* showAllTrip: 是否显示所有数据标记
*/
function boundChart(cData:Object,cleng:String,showAllTrip:Boolean=false):void
{
var o:* = cData;
var dataCollection:ArrayCollection = getArrayCollection(o.date,o.data);
chart1.init(dataCollection,cleng,o.title,o.xtitle,showAllTrip);
chart2.init(dataCollection,cleng,o.title,o.xtitle,showAllTrip);
}
public function getArrayCollection(arrLabels:Array,arrValues:Array):ArrayCollection
{
var result:ArrayCollection = null;
var length:int = arrLabels.length;
if(arrLabels != null && arrValues != null && length== arrValues.length)
{
result = new ArrayCollection();
for(var i:int=0;i<length;i++)
{
result.addItem({label:arrLabels[i], value:Number(arrValues[i])});
}
}
return result;
}
]]-->
</mx:Script>
<mx:HBox>
<mx:Panel title="圆柱图" width="395" height="300">
<chart:ClumnChart id="chart1">
</chart:ClumnChart>
</mx:Panel>
<mx:Panel title="立方图" width="395" height="300">
<chart:solidChart id="chart2">
</chart:solidChart>
</mx:Panel>
</mx:HBox>
</mx:Application>