【转载】VML习作——扇形图

来源:互联网 发布:淘宝解封lol 编辑:程序博客网 时间:2024/05/01 11:00


上个月写了一篇VML习作——折线图,今天再把制作的扇形图贴出来。做扇形图颇费周折,在网上找了一些例子,但是都只有最后出来的效果图,根本无法看出来他是如何计算,在美洲豹的Thinking in VML教程中,是利用了path的一个ac参数来做的,但是他要把角度转换为弧度,还有些其他计算,怎么也没有看明白。

最后发现利用path的ae参数作扇形图是最佳的选择,好理解也好计算。看看W3C网站上面对ae的解释:
 ommand: ae
Name: angleellipseto
parameters: 6
Description: center (x,y) size(w,h) start-angle, end-angle. Draw a segment of an ellipse as describes using these parameters. A straight line is drawn from the current point to the start point of the segment.
引用内容 引用内容
最后两个参数就是扇形所张开的角度,只是让人费解的是要把角度值乘以2^16,也就是65536。还有start-angle是起始角度,但是end-angle并不是结束角度,end-angle应该是扇形张开所经过的角度数,这个我试验了很久才弄明白。

下面是全部代码,欢迎有兴趣的网友与我交流。
<html xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>无标题文档</title>
<script language="JavaScript" type="text/javascript">
function Pie(r,item_t,item_v){
 //r半径,item_t项目的标题,item_v项目的值
 var i,s;
 var item_p=new Array(); //各个项目的比例
 var item_q=new Array(); //各个项目的百分比
 var sum=0; //项目总和
 var len=item_t.length; //项目个数
 
 var d=r*2; //直径
 //定义颜色
 var color1=new Array("#d1ffd1","#ffbbbb","#ffe3bb","#cff4f3","#d9d9e5","#ffc7ab","#ecffb7");
 var color2=new Array("#00ff00","#ff0000","#ff9900","#33cccc","#666699","#993300","#99cc00");
 
 for(i=0;i<len;i++)
  sum+=item_v[i];
 for(i=0;i<len;i++){
  item_p[i]=item_v[i]/sum;
  item_q[i]=FormatNumber(item_p[i]*100,1)+"%";
 }
 
 s="<v:group style='width:"+(d+230)+"px;height:"+d+"px' coordsize='"+(d+230)+","+d+"'>";
 //背景
 s+="<v:rect style='left:-5;top:-5;width:"+(d+235)+";height:"+(d+10)+"'>";
 s+="<v:shadow on='t' type='single' color='silver' offset='5px,5px' />";
 s+="</v:rect>";
 //扇形
 var angle1=0;
 var angle2;
 for(i=0;i<len;i++){
  angle2=parseInt(360*item_p[i]);
  if(i==len-1)
   angle2=360-angle1;
  s+="<v:shape title='"+item_t[i]+":"+item_q[i]+"' style='position:absolute;width:"+d+";height:"+d+"' coordsize='"+d+","+d+"' strokeweight='1' strokecolor='#fff' fillcolor='"+color1[i]+"' path='m "+r+","+r+" ae "+r+","+r+","+r+","+r+","+65536*angle1+","+65536*angle2+" x e'>";
  s+="<v:fill color2='"+color2[i]+"' rotate='t' focus='100%' type='gradient' />";
  s+="</v:shape>"
  angle1+=angle2;
 }
 
 //各个项目说明
 s+="<v:group style='position:absolute;left:"+(d+25)+";top:"+(d-(22*len+12))+";width:200;height:"+(22*len+4)+"' coordsize='200,"+(22*len+4)+"'>";
 s+="<v:rect style='width:200;height:"+(22*len+4)+"' strokecolor='#333' />";
 for(i=0;i<len;i++){
  s+="<v:rect style='left:4;top:"+(i*22+4)+";width:25;height:18;' title='"+item_t[i]+":"+item_q[i]+"' fillcolor='"+color1[i]+"'><v:fill color2='"+color2[i]+"' rotate='t' focus='100%' type='gradient' /></v:rect>";
  s+="<v:shape style='left:30;top:"+(i*22+4)+";width:200;height:25'><v:textbox inset='0,0,0,0'><table><td style='font-size:10px'>"+item_t[i]+":"+item_v[i]+"("+item_q[i]+")</td></table></v:textbox></v:shape>";
 }
 s+="</v:group>";
 s+="</v:group>";
 
 document.write(s);
}
function FormatNumber(srcStr,nAfterDot){
 var srcStr,nAfterDot;
 var resultStr,nTen;
 srcStr = ""+srcStr+"";
 strLen = srcStr.length;
 dotPos = srcStr.indexOf(".",0);
 if (dotPos == -1){
  resultStr = srcStr+".";
  for (i=0;i<nAfterDot;i++)
   resultStr = resultStr+"0";
  return resultStr;
 }
 else{
  if ((strLen - dotPos - 1) >= nAfterDot){
   nAfter = dotPos + nAfterDot + 1;
   nTen =1;
   for(j=0;j<nAfterDot;j++)
    nTen = nTen*10;
   resultStr = Math.round(parseFloat(srcStr)*nTen)/nTen;
   return resultStr;
  }
  else{
   resultStr = srcStr;
   for (i=0;i<(nAfterDot - strLen + dotPos + 1);i++)
    resultStr = resultStr+"0";
   return resultStr;
  }
 }
}
</script>
<style type="text/css">
<!--
v/:* { Behavior: url(#default#VML) }
body,td,th,p {
 font-size: 12px;
 font-family: Verdana, Arial, Helvetica, sans-serif;
}
-->
</style>
</head>
<body>
<script language="JavaScript" type="text/javascript">
var x=new Array("Google","百度","Yahoo","3721","MSN Search","其他");
var y=new Array(210,100,180,130,90,20);
Pie(100,x,y);
</script>
</body>
</html>
command: ae
Name: angleellipseto
parameters: 6
Description: center (x,y) size(w,h) start 
VML习作——折线图
在一个Web开发项目中需要用到统计图,所以从头开始接触VML(Vector Markup Language),这在以前是从没有听说过的东西,唉孤陋寡闻很多年了。

折线图
以下算是我的第一个完成好的VML折线图,记录下来:
<html xmlns:v = "urn:schemas-microsoft-com:vml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>VML</title>
<style type="text/css">
v/:* { Behavior: url(#default#VML) }
</style>
<script language="JavaScript" type="text/javascript">
function Chart_Draw(title,width,height,xy){
 var s,i,fn;
 var p="";
 var x=Array(9)
 var y=Array(9)
 
 fn="躯体化|强迫症状|人际敏感|抑郁|焦虑|敌对|恐怖|偏执|精神病性|其他".split("|");
 for(i=0;i<10;i++){
  x[i]=i*100;
  y[i]=400-(xy[i]-1)*100;
  p+=x[i]+","+y[i]+" ";
 }
 
 s="<v:group style='width:"+width+"px; height:"+height+"px' coordsize='1000,500'>";
 //背景
 s+="<v:rect style='width:1005;height:500' fillcolor='white' strokecolor='black'>";
 s+="<v:shadow on='t' type='single' color='silver' offset='5px,5px' />";
 s+="</v:rect>";
 //标题
 s+="<v:Rect style='position:absolute;top:5;width:1000;height:50' stroked='f'>";
 s+="<v:TextBox style='font-size:14px; font-weight:bold; text-align:center'>"+title+"</v:TextBox>";
 s+="</v:Rect>";
 //曲线图坐标网格
 s+="<v:group style='position:absolute;top:50px;left:60px;width:900px;height:400px' coordsize='900,400' coordorig='0,400'>";
 s+="<v:rect style='width:900px;height:400px' strokecolor='#ccc' />";
 //横向网格
 for(i=1;i<=40;i++){
  s+="<v:line from='0,"+i*10+"' to='900,"+i*10+"'>";
  if(i==20)
   s+="<v:stroke color='#F90' />";
  else if(i%10==0)
   s+="<v:stroke color='#ccc' />";
  else
   s+="<v:stroke color='#ccc' dashstyle='shortdash' />";
  s+="</v:line>";
 }
 //纵向网格
 for(i=1;i<=8;i++){
  s+="<v:line from='"+i*100+",0' to='"+i*100+",400' strokecolor='#ccc' />";
 }
 //曲线
 s+="<v:polyline style='position:absolute' strokecolor='green' filled='f' strokeweight='1px' points='"+p+"' />";
 //各个折点
 for(i=0;i<10;i++){
  s+="<v:rect style='position:absolute;left:"+(x[i]-4)+";top:"+(y[i]-4)+";width:8;height:8' title='"+fn[i]+":"+xy[i]+"' fillcolor='red' stroked='f' />";
  s+="<v:shape style='position:absolute;left:"+(x[i]+10)+";top:"+(y[i]-8)+";width:35;height:30;font-size:10px;font-weight:bold;color:#666'>"+xy[i]+"</v:shape>";
 }
 s+="</v:group>";
 //底部项目
 for(i=0;i<fn.length;i++){
  s+="<v:shape style='position:absolute;left:"+(20+i*100)+";top:460;width:80;height:30;text-align:center;font-size:12px'>"+fn[i]+"</v:shape>";
 }
 //左边项目
 for(i=1;i<6;i++){
  s+="<v:shape style='position:absolute;left:30;top:"+(i*100-57)+";width:30;height:100;text-align:center;font-size:12px'>"+(6-i)+"</v:shape>";
 }
 s+="</v:group>";
 document.write(s);
}
</script>
</head>
<body>
<script language="JavaScript" type="text/javascript">
//折线段上的各个转点
var xy=new Array(3,3.1,1.67,2.77,2.5,2,3.5,2.33,4,2.6);
//输入图形,其中宽和高可以更改
Chart_Draw("《SCL-90症状自评》测评结果分析图",700,350,xy);
</script>
</body>
</html>
心得
虽然结果如我想象的出来了,但是其中也包含辛酸和泪水啊(是挺酸的),有几个问题时试验了很久才弄明白的:
1、<v:group>这个元素的width、height和coordsize的关系,以及子元素位置和尺寸的表示。coordsize是坐标,width和height是他呈现出来的实际尺寸,如果coordsize="1000,500",width和height分别是800px和400px,那么子元素的left、top、width、height的单位就以1000和500为基准了,而不管是否带单位px。例如<v:group>里面一个<v:rect>,和四边的距离都是100,那么就应该写成:<v:rect style="left:100;top:100;width:800;height:300" />,这里的width和height就是坐标值了,那么实际尺寸有多大呢,这个就不一定了,取决于<v:group>元素width和height的取值。好晕啊~~~。

2、坐标上的刻度。按美洲豹的Thinking in VML所说的,用绝对定位的<p>来实现,但在实际操作中有点儿问题,如果这个图形放大或者缩小以后,坐标上的刻度位置就变了。我怀疑可能是因为如果不是VML标签(例如P标签),那么其定位并不遵循坐标值,而是用的真实像素置。所以后来自己用<v:shape>标签来表示坐标上的刻度,经放大缩小试验均保持在原来位置。

3、为了在正式勾画折线的时候坐标值方便计算,在外层<v:group>内再嵌套一个和折线坐标大小相同的<v:group>,这样折线的坐标值就基于内层的<v:group>的坐标,很容易计算,不会受到其他对象的干扰。

4、如果折线和坐标线的出现顺序与上例并不一样,那么保险的方法是加入z-index属性,该属性用数字表示,数字越大表示越浮动于上层。

存疑
1、<v:group>的coordorig(坐标原点)属性不太好理解,我给这个属性设定任意值,但是图形没有任何变化,不解中...
2、想让坐标原点从左下角开始,这样计算每个点的坐标值正好是其真实值,而不用计算差值,不知道怎么实现,用coordorig属性好象并不能实现这种效果。

更多...
另外给出几个网址,感兴趣的朋友可以去研究一下:
  • 微软的官方站:http://msdn.microsoft.com/workshop/author/vml/default.asp
  • W3C:http://www.w3.org/TR/NOTE-VML
  • 这儿有很多巨强的例子,老外的:http://www.causeway.co.uk/demos/vml/index.htm
  • 用Javascript类和VML做饼图:http://blog.csdn.net/liuruhong/category/9094.aspx
  • VML极道教程:http://www.lshdic.cn/vmljdjc.htm
  • 美洲豹的Thinking in VML:http://www.itlearner.com/code/vml/index.html
  • 好象是一个JS的类,没完全看明白:http://webfx.eae.net/dhtml/chart/chart.html
  • 几个不错的实例:三维饼图、三维柱状图、饼图、柱状图
http://www.ziyuehome.com/article.asp?id=90
原创粉丝点击