上个月写了一篇 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.
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; //直径
<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];
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+"'>";
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>";
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>";
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);
}
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>
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
Name: angleellipseto
parameters: 6
Description: center (x,y) size(w,h) start
VML习作——折线图
在一个Web开发项目中需要用到统计图,所以从头开始接触
VML(Vector Markup Language),这在以前是从没有听说过的东西,唉孤陋寡闻很多年了。
折线图
以下算是我的第一个完成好的VML折线图,记录下来:
折线图
以下算是我的第一个完成好的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>
<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属性好象并不能实现这种效果。
更多...
另外给出几个网址,感兴趣的朋友可以去研究一下:
虽然结果如我想象的出来了,但是其中也包含辛酸和泪水啊(是挺酸的),有几个问题时试验了很久才弄明白的:
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
- 几个不错的实例:三维饼图、三维柱状图、饼图、柱状图