as2.0绘制饼图类

饼图因为能直观的表现数据比例,所以被广泛的应用。

这个程序的核心部分不是我写的,具体可以看http://www.blueidea.com/tech/multimedia/2007/4540.asp

本类就是在amu945基础上修改所得,还很不完善,但是就像原作者所说——可以用,希望您喜欢。

主要修改为:
1 将代码整理成类,规范了代码
2 引入XpathAPI,提高数据配置的灵活性
3 设定数据初值,防止出错

使用方法:
xml数据文件

XML:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <root>
  3. <config x0="210" y0="135" z="150" d="90" w="150" h="20" movew="15" alpha="100" mcalpha="100" showorder="true" orderx="480" ordery="70" orderxy="40" linecolor="0xcccccc" linealpha="100" titleline="20" fontcolor="0xFF0000" percentshow="font" orderfontcolor="0x222222"/>
  4. <vote pieNum="20" pieName="四川" showName="true" colorString="0xFF0F00" defaultState="false"/>
  5. <vote pieNum="15" pieName="重庆" showName="true" colorString="0xFF6600" defaultState="false"/>
  6. <vote pieNum="8" pieName="湖南" showName="true" colorString="0xFCD202" defaultState="true"/>
  7. </root>

具体参数为:
x0,y0圆心坐标;
w1,w2为长短轴;
a0为开始度数,a为结束度数,
h为高, hw为环宽,
color为十六进制颜色,
movew为移动距离,
alpha为透明度(点击之后),mcalpha为原始透明度,
titleline显示名称与值的长短位置,linecolor指示线颜色,linealpha指示线透明度,
fontcolor文字颜色,percentshow是否显示百分比值,dark深色系数(>1如1.43),
defaultState为确定默认载入时是否移动出去,
pieNum为数值,pieName为名称,showName确定是否显示名称与值。

然后在Action面板中写入:

Actionscript:
  1. import Caky.as;
  2. var mc:MovieClip=_root.createEmptyMovieClip("mc",_root.getNextHighestDepth());
  3. var myCaky:Caky=new Caky(mc,"aaa.xml");

发布完成就可以了。
饼图演示

类代码:

Actionscript:
  1. /*
  2. Class Name:Caky
  3. update:2007,3,18
  4. coder:amu945(http://www.myvapor.com/web)
  5.       残缺(http://www.rssidea.com)
  6. */
  7. import mx.transitions.Tween;
  8. import mx.transitions.easing.*;
  9. import mx.xpath.XPathAPI;
  10. class Caky {
  11.     private var voteArray:Array = new Array();
  12.     public function Caky(mc:MovieClip, xmlFile:String) {
  13.         var thisObj = this;
  14.         var xmlObj:XML = new XML();
  15.         xmlObj.ignoreWhite = true;
  16.         xmlObj.onLoad = function(success:Boolean) {
  17.             if (success) {
  18.                 var votePath:String = "/root/vote";
  19.                 var configPath:String = "/root/config";
  20.                 var tempArray:Array = XPathAPI.selectNodeList(this.firstChild, votePath);
  21.                 var configNode:XMLNode = XPathAPI.selectSingleNode(this.firstChild, configPath);
  22.                 var configObj:Object = configNode.attributes;
  23.                 for (var i:Number = 0; i<tempArray.length; i++) {
  24.                     var tempObj:Object = tempArray[i].attributes;
  25.                     thisObj.voteArray[i]=tempObj;
  26.                 }
  27.                 delete this;
  28.                 thisObj.drawPie(mc, "test", mc.getNextHighestDepth(), thisObj.voteArray, configObj);
  29.             } else {
  30.                 trace("loading xml error! Do please check your net connection!");
  31.             }
  32.         };
  33.         xmlObj.load(xmlFile);
  34.     }
  35.     private function drawPie(targetMc:MovieClip, mcName:String, depth:Number, voteArray:Array, configObj:Object):Void {
  36.         //读取vote数据
  37.         var voteNameArray:Array = new Array(), voteNumArray:Array = new Array(), isShowNameArray:Array = new Array(), arr_color:Array = new Array(), stateArray:Array = new Array();
  38.         var voteTotal:Number = 0;
  39.         for (var i:Number = 0; i<voteArray.length; i++) {
  40.             voteNameArray[i] = voteArray[i].pieName || "未标题";
  41.             voteNumArray[i] = Number(voteArray[i].pieNum) || 0;
  42.             arr_color[i] = voteArray[i].colorString || 0x000000;
  43.             voteTotal += voteNumArray[i];
  44.             isShowNameArray[i] = (voteArray[i].showName == "true") ? true : false;
  45.             stateArray[i] = (voteArray[i].defaultState == "true") ? true : false;
  46.         }
  47.         //加载配置选项
  48.         var x0:Number = Number(configObj.x0)||0;
  49.         var y0:Number = Number(configObj.y0)||0;
  50.         var z:Number = Number(configObj.z)||100;
  51.         var d:Number = Number(configObj.d)||60;
  52.         var w:Number = Number(configObj.w)||150;
  53.         var h:Number = Number(configObj.h)||20;
  54.         var movew:Number = Number(configObj.movew)||15;
  55.         var alpha:Number = Number(configObj.alpha)||100;
  56.         var mcalpha:Number = Number(configObj.mcalpha)||100;
  57.         var showorder:Boolean = configObj.showorder=="true"?true:false;
  58.         var orderx:Number = Number(configObj.orderx)||250;
  59.         var ordery:Number = Number(configObj.ordery)||10;
  60.         var orderxy:Number = Number(configObj.orderxy)||5;
  61.         var linecolor:Number = Number(configObj.linecolor)||0x666666;
  62.         var linealpha:Number = Number(configObj.linealpha)||80;
  63.         var titleline:Number = Number(configObj.titleline)||0x333333;
  64.         var fontcolor:Number = Number(configObj.fontcolor)||0x000000;
  65.         var percentshow:String = configObj.percentshow;
  66.         var orderfontcolor:Number = Number(configObj.orderfontcolor)||0x000000;
  67.         var dark:Number = Number(configObj.dark)||1.4;
  68.         //计算百分比值
  69.         var arr_percent:Array = new Array(), arr_num:Array = new Array();
  70.         var duof:Number = 0, duo:Number = 0;
  71.         for (var m:Number = 0; m<voteNumArray.length; m++) {
  72.             if (m == voteNumArray.length-1) {
  73.                 duo = 360-duof;
  74.                 arr_num[m] = duo.toString();
  75.             } else {
  76.                 duo = Math.round((Number(voteNumArray[m])*360)/voteTotal);
  77.                 duof = duof+duo;
  78.                 arr_num[m] = duo.toString();
  79.             }
  80.             arr_percent[m] = Math.round((Number(voteNumArray[m])*100)/voteTotal*100)/100;
  81.         }
  82.         //所有扇环的中间度
  83.         var arr_middle:Array = new Array();
  84.         //生成所有的扇环的中间度,用来确定深度
  85.         var xx:Number = -90, a0:Number, a:Number;
  86.         var arr_a:Array = new Array();
  87.         //记录每一扇环的开始度与结束度
  88.         for (m=0; m<arr_num.length; m++) {
  89.             a0 = xx;
  90.             a = Number(a0)+Number(arr_num[m]);
  91.             arr_a.push([a0, a]);
  92.             xx = a;
  93.             if (a-a0>180) {
  94.                 arr_middle[m] = 0.001;
  95.             } else {
  96.                 if ((a-a0)/2+a0<=180 && (a-a0)/2+a0>=0) {
  97.                     //本mc的中间角度与90度的差值(这儿我们确定谁与90度差值的绝对值最小就排在最前面)
  98.                     arr_middle[m] = Math.abs(90-((a-a0)/2+a0));
  99.                 } else if ((a-a0)/2+a0>180 && (a-a0)/2+a0<=270) {
  100.                     arr_middle[m] = (Math.abs((a-a0)/2+a0-180)+500);
  101.                     //本mc的中间角度与180度的差值(这儿我们确定谁与90度差值的绝对值最大就排在最前面)
  102.                 } else if ((a-a0)/2+a0>=-90 && (a-a0)/2+a0<0) {
  103.                     arr_middle[m] = (Math.abs((a-a0)/2+a0-360)+500);
  104.                     //本mc的中间角度与270度的差值(这儿我们确定谁与90度差值的绝对值最大就排在最前面)
  105.                 }
  106.             }
  107.         }
  108.         //扇环排序
  109.         arr_middle = arr_middle.sort(Array.NUMERIC | Array.RETURNINDEXEDARRAY);
  110.         //重排序,让原来的数组值从小到大排列,但数组的索引不变。
  111.         for (var m:Number = 0; m<arr_middle.length; m++) {
  112.             //绘出竖向方块链接------------------------------------------------------------------------
  113.             if (showorder) {
  114.                 targetMc.createEmptyMovieClip(mcName+arr_middle[m]+"icon_mc", (5-m)*22+depth*10+1);
  115.                 var mc:MovieClip = targetMc[mcName+arr_middle[m]+"icon_mc"];
  116.                 var color:Number, beginx:Number, beginy:Number, jianxy:Number;
  117.                 color = parseInt(arr_color[arr_middle[m]]);
  118.                 beginx = orderx;
  119.                 beginy = ordery;
  120.                 jianxy = orderxy+12;
  121.                 mc.beginFill(color, 100);
  122.                 mc.lineStyle(1, this.darkColor(color, dark), 100, true, "none");
  123.                 mc.moveTo(beginx, arr_middle[m]*jianxy+beginy);
  124.                 mc.lineTo(beginx+12, arr_middle[m]*jianxy+beginy);
  125.                 mc.lineTo(beginx+12, arr_middle[m]*jianxy+beginy+12);
  126.                 mc.lineTo(beginx, arr_middle[m]*jianxy+beginy+12);
  127.                 mc.endFill();
  128.                 var label:TextField = mc.createTextField("label", 1, beginx+16, arr_middle[m]*jianxy+beginy-3, 0, 0);
  129.                 label.html = true;
  130.                 label.autoSize = "left";
  131.                 label.htmlText = voteNameArray[arr_middle[m]];
  132.                 var myformat:TextFormat = new TextFormat();
  133.                 myformat.font = "Verdana";
  134.                 myformat.size = 12;
  135.                 myformat.color = orderfontcolor;
  136.                 label.setTextFormat(myformat);
  137.             }
  138.             //---------------------------------------------------------------------         
  139.             targetMc.createEmptyMovieClip(mcName+arr_middle[m]+"_mc", (5-m)*22+depth*10);
  140.             //当前m应算为arr_middle[m];
  141.             this.drawCircle(targetMc[mcName+arr_middle[m]+"_mc"], x0, y0, z, d, arr_a[arr_middle[m]][0], arr_a[arr_middle[m]][1], h, w, parseInt(arr_color[arr_middle[m]]), movew, alpha, mcalpha, stateArray[arr_middle[m]], arr_percent[arr_middle[m]], voteNameArray[arr_middle[m]], isShowNameArray[arr_middle[m]], titleline, linecolor, linealpha, fontcolor, percentshow, dark, targetMc[mcName+arr_middle[m]+"icon_mc"]);
  142.             this[mcName+arr_middle[m]+"_mc"]._alpha = mcalpha;
  143.             //---------------------------------------------------------------------
  144.             //让点击竖向排列时的效果和点击pie时一样。
  145.             if (showorder) {
  146.                 mc.onRelease = this[mcName+arr_middle[m]+"_mc"].onRelease;
  147.             }
  148.         }
  149.     }
  150.     /*
  151.     mc为影片名。
  152.     x0,y0圆心坐标;w1,w2为长短轴;a0为开始度数,a为结束度数,h为高, hw为环宽,color为十六进制颜色,
  153.     movew为移动距离,alpha为透明度(点击之后),mcalpha为原始透明度,movenow为确定默认载入时是否移动出去,
  154.     valuepercent为百分比值,arr_name为每项名称,arr_showname确定是否显示名称与值,
  155.     titleline显示名称与值的长短位置,linecolor指示线颜色,linealpha指示线透明度,fontcolor文字颜色,percentshow是否显示百分比值,dark深色系数(>1如1.43)
  156.     本pie对应竖向排列方块mc名。
  157.     */
  158.     function drawCircle(mc:MovieClip, x0:Number, y0:Number, w1:Number, w2:Number, a0:Number, a:Number, h:Number, hw:Number, color:Number, movew:Number, alpha:Number, mcalpha:Number, movenow:String, valuepercent:Number, arr_name:String, arr_showname:String, titleline:Number, linecolor:Number, linealpha:Number, fontcolor:Number, percentshow:String, dark:Number, ordermc:MovieClip):Void {
  159.         var step:Number, leichang:Number, leiduan:Number, hicolor:Number, k:Number;
  160.         var thisObj = this;
  161.         //加减间隔度
  162.         step = 1;
  163.         //求内长短轴
  164.         leichang = w1-hw;
  165.         leiduan = w2-(hw*w2/w1);
  166.         //深色
  167.         hicolor = this.darkColor(color, dark);
  168.         //---------------------------------
  169.         //下面为下面环;
  170.         mc.beginFill(color, 100);
  171.         //mc.lineStyle(1, color, 100, false, "none");
  172.         //外边
  173.         mc.moveTo(this.getPoint(x0, y0+h, w1, w2, a0).x, this.getPoint(x0, y0+h, w1, w2, a0).y);
  174.         k = a0;
  175.         while (k<a) {
  176.             k += step;
  177.             mc.lineTo(this.getPoint(x0, y0+h, w1, w2, k).x, this.getPoint(x0, y0+h, w1, w2, k).y);
  178.         }
  179.         //侧边1
  180.         mc.lineTo(this.getPoint(x0, y0+h, leichang, leiduan, k).x, this.getPoint(x0, y0+h, leichang, leiduan, k).y);
  181.         //内边
  182.         while (k>a0) {
  183.             k -= step;
  184.             mc.lineTo(this.getPoint(x0, y0+h, leichang, leiduan, k).x, this.getPoint(x0, y0+h, leichang, leiduan, k).y);
  185.         }
  186.         //侧边2
  187.         mc.lineTo(this.getPoint(x0, y0+h, leichang, leiduan, a0).x, this.getPoint(x0, y0+h, leichang, leiduan, a0).y);
  188.         mc.endFill();
  189.         //--------------------------------
  190.         //下边高
  191.         //下边外侧边高
  192.         if (a0<=0 && a>=0 && a<=180) {
  193.             //解决90度时外侧面,显示事实为90度,实际为0度,因为我们整个旋转了-90度;
  194.             mc.beginFill(hicolor, 100);
  195.             mc.moveTo(this.getPoint(x0, y0+h, w1, w2, a0).x, this.getPoint(x0, y0+h, w1, w2, a0).y);
  196.             k = a0;
  197.             while (k<0) {
  198.                 k += step;
  199.                 mc.lineTo(this.getPoint(x0, y0+h, w1, w2, k).x, this.getPoint(x0, y0+h, w1, w2, k).y);
  200.             }
  201.             mc.lineTo(this.getPoint(x0, y0, w1, w2, 0).x, this.getPoint(x0, y0, w1, w2, 0).y);
  202.             while (k>a0) {
  203.                 k -= step;
  204.                 mc.lineTo(this.getPoint(x0, y0, w1, w2, k).x, getPoint(x0, y0, w1, w2, k).y);
  205.             }
  206.             mc.endFill();
  207.             mc.beginFill(hicolor, 100);
  208.             mc.moveTo(getPoint(x0, y0+h, w1, w2, 0).x, this.getPoint(x0, y0+h, w1, w2, 0).y);
  209.             k = 0;
  210.             while (k<a) {
  211.                 k += step;
  212.                 mc.lineTo(this.getPoint(x0, y0+h, w1, w2, k).x, this.getPoint(x0, y0+h, w1, w2, k).y);
  213.             }
  214.             mc.lineTo(this.getPoint(x0, y0, w1, w2, a).x, this.getPoint(x0, y0, w1, w2, a).y);
  215.             while (k>0) {
  216.                 k -= step;
  217.                 mc.lineTo(this.getPoint(x0, y0, w1, w2, k).x, this.getPoint(x0, y0, w1, w2, k).y);
  218.             }
  219.             mc.endFill();
  220.         } else if (a>=180 && a0<=180 && a0>=0) {
  221.             //解决180度时外侧面,显示事实为270度,实际为180度,因为我们整个旋转了-90度;
  222.             mc.beginFill(hicolor, 100);
  223.             mc.moveTo(this.getPoint(x0, y0+h, w1, w2, a0).x, this.getPoint(x0, y0+h, w1, w2, a0).y);
  224.             k = a0;
  225.             while (k<180) {
  226.                 k += step;
  227.                 mc.lineTo(this.getPoint(x0, y0+h, w1, w2, k).x, this.getPoint(x0, y0+h, w1, w2, k).y);
  228.             }
  229.             mc.lineTo(this.getPoint(x0, y0, w1, w2, 180).x, this.getPoint(x0, y0, w1, w2, 180).y);
  230.             while (k>a0) {
  231.                 k -= step;
  232.                 mc.lineTo(this.getPoint(x0, y0, w1, w2, k).x, this.getPoint(x0, y0, w1, w2, k).y);
  233.             }
  234.             mc.endFill();
  235.             mc.beginFill(hicolor, 100);
  236.             mc.moveTo(this.getPoint(x0, y0+h, w1, w2, 180).x, this.getPoint(x0, y0+h, w1, w2, 180).y);
  237.             k = 180;
  238.             while (k<a) {
  239.                 k += step;
  240.                 mc.lineTo(this.getPoint(x0, y0+h, w1, w2, k).x, this.getPoint(x0, y0+h, w1, w2, k).y);
  241.             }
  242.             mc.lineTo(this.getPoint(x0, y0, w1, w2, a).x, this.getPoint(x0, y0, w1, w2, a).y);
  243.             while (k>180) {
  244.                 k -= step;
  245.                 mc.lineTo(this.getPoint(x0, y0, w1, w2, k).x, this.getPoint(x0, y0, w1, w2, k).y);
  246.             }
  247.             mc.endFill();
  248.         } else if (a0<=0 && a>=180) {
  249.             //解决同时处于0度和180度的情况
  250.             mc.beginFill(hicolor, 100);