【轉載】VML習作——扇形圖



上個月寫了一篇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屬性好象並不能實現這種效果。

更多...
另外給出幾個網址,感興趣的朋友可以去研究一下:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章