基于VML实现的饼图

liuruhong 上择创想 2003-08-18 04:51:10
采用JavaScript和VML做了一个饼图的Class,以下是源代码,欢迎大家下载并提供一点意见
--------------------------------------------------------
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
<title></title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="ProgId" content="VisualStudio.HTML">
<meta name="Originator" content="Microsoft Visual Studio .NET 7.1">
<STYLE> v\:* { BEHAVIOR: url(#default#VML) }
o\:* { BEHAVIOR: url(#default#VML) }
.shape { BEHAVIOR: url(#default#VML) }
</STYLE>
<script language="javascript">
function VMLPie(pWidth,pHeight,pCaption,pContainer){
this.Container=pContainer;
this.Width= pWidth || "400px";
this.Height=pHeight || "250px";
this.Caption = pCaption || "VML Chart";
this.backgroundColor="";
this.Shadow=false;
this.BorderWidth=0;
this.BorderColor=null;
this.all=new Array();
this.id=document.uniqueID;
this.RandColor=function(){

return "rgb("+ parseInt( Math.random() * 255) +"," +parseInt( Math.random() * 255) +"," +parseInt( Math.random() * 255)+")";
}
this.VMLObject=null;
this.LegendObject=null;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//接口功能:
// 开始画图,将图形画到指定的容器上面
/////////////////////////////////////////////////////////////////////////////////////////////////
VMLPie.prototype.Draw=function(){
//画外框
var o=document.createElement("v:group");
o.id=this.id;
o.style.width=this.Width;
o.style.height=this.Height;
o.coordsize="21600,21600";
//添加一个背景层
var vRect=document.createElement("v:rect");
vRect.style.width="21600px"
vRect.style.height="21600px"
o.appendChild(vRect);
//添加标题
var vCaption=document.createElement("v:textbox");
vCaption.style.fontSize="24px";
vCaption.style.height="24px"
vCaption.preSize="24";
vCaption.style.fontWeight="bold";
vCaption.innerHTML=this.Caption;
vCaption.style.textAlign="center";

vRect.appendChild(vCaption);
//设置边框大小
if(this.BorderWidth){
vRect.strokeweight=this.BorderWidth;
}
//设置边框颜色
if(this.BorderColor){
vRect.strokecolor=this.BorderColor;
}
//设置背景颜色
if(this.backgroundColor){
vRect.fillcolor=this.backgroundColor;
}
//设置是否出现阴影
if(this.Shadow){
var vShadow=document.createElement("v:shadow");
vShadow.on="t";
vShadow.type="single";
vShadow.color="graytext";
vShadow.offset="4px,4px";
vRect.appendChild(vShadow);
}
this.VMLObject=o;


//开始画内部园
var oOval=document.createElement("v:oval");
oOval.style.width="15000px";
oOval.style.height="14000px";
oOval.style.top="4000px";
oOval.style.left="1000px";
oOval.fillcolor="#d5dbfb";

//本来计划加入3D的效果,后来感觉确实不好控制,就懒得动手了
//var o3D=document.createElement("o:extrusion");
var formatStyle=' <v:fill rotate="t" angle="-135" focus="100%" type="gradient"/>';
//formatStyle+='<o:extrusion v:ext="view" color="#9cf" on="t" rotationangle="-15"';
//formatStyle+=' viewpoint="0,34.72222mm" viewpointorigin="0,.5" skewangle="105"';
//formatStyle+=' lightposition="0,50000" lightposition2="0,-50000"/>';
formatStyle+='<o:extrusion v:ext="view" backdepth="1in" on="t" viewpoint="0,34.72222mm" viewpointorigin="0,.5" skewangle="90" lightposition="-50000" lightposition2="50000" type="perspective"/>';
oOval.innerHTML=formatStyle;

//o.appendChild(oOval);
this.CreatePie(o);

return o.outerHTML;
//this.Container.appendChild(o); //插入

}
...全文
66 点赞 收藏 19
写回复
19 条回复
yibotiemen 2003年10月16日
我复制下来有错误
能够给各测试连接吗?
回复 点赞
Naola2001 2003年09月12日
mark 一下
回复 点赞
cpio 2003年09月12日
高深
回复 点赞
liuruhong 2003年09月12日
VML是一个表基语言,基于xml的一个应用,和HTML接近,只是元素不通而已,在IE5+支持
回复 点赞
csdnxw 2003年09月12日
VML需要什么语言支持么?
用javascript就可以编写了么?
回复 点赞
yaray 2003年09月12日
不好意思,找着是哪里了 :)
回复 点赞
yaray 2003年09月12日
运行到p.innerText=vPieEl.outerHTML;出错

sorry,注释了就可以了,那个代码没有用

可是我注释掉了还出错?
回复 点赞
chjpeng 2003年08月30日
好!
回复 点赞
jackie615 2003年08月30日
不错 精神更可嘉啊!

多出好东西就多捧场:)
回复 点赞
liuruhong 2003年08月30日
本来希望直接使用DOM的attachEvent,可是后来发现不行
回复 点赞
okodoov 2003年08月30日
回复 点赞
linhaibo 2003年08月29日
不错,加入了鼠标事件~~ 收藏
回复 点赞
liuruhong 2003年08月29日
sorry,注释了就可以了,那个代码没有用
回复 点赞
scycgjr 2003年08月29日
运行到p.innerText=vPieEl.outerHTML;出错
回复 点赞
liuruhong 2003年08月18日
var objPie=null;
//以下是函数调用
function DrawPie(){
objPie=new VMLPie("600px","450px","人口统计图"); //初始化宽度,高度,标题
objPie.BorderWidth=3; //图表边框
objPie.BorderColor="blue"; //图表边框颜色
objPie.Width="800px"; //定义图表宽度
objPie.Height="600px"; //定义图表高度
objPie.backgroundColor="#ffffff"; //定义背景颜色
objPie.Shadow=true; //是否需要阴影 true为是 false为不要阴影
//添加图表数据
//顺序为名称,值,描述
objPie.AddData("北京",50,"北京的人口");
objPie.AddData("上海",52,"上海的固定人口");
objPie.AddData("天津",30,"天津的外地人口");
objPie.AddData("西安",58,"西安城市人口");
objPie.AddData("武汉",30,"武汉的外地人口");
objPie.AddData("重庆",58,"重庆城市人口");
result.innerHTML=objPie.Draw(); //生成VML数据

//alert(document.body.outerHTML);
}


</script>
</head>
<body onload="DrawPie()">
<select id="zoom" onchange="objPie.Zoom(this.value);" NAME="zoom">
<option value="0.2" selected>20%</option>
<option value="0.25">25%</option>
<option value="0.4">40%</option>
<option value="0.5">50%</option>
<option value="0.75">75%</option>
<option value="0.8">80%</option>
<option value="1">原始大小</option>
<option value="1.25">125%</option>
<option value="1.5">150%</option>
<option value="2">200%</option>
<option value="3">300%</option>
<option value="4">400%</option>
</select>
<OBJECT id="MyScroll" title="改变滚动条的值,右边的图片会相应的旋转" height="15" width="100" classid="CLSID:DFD181E0-5E2F-11CE-A449-00AA004A803D"
VIEWASTEXT>
<PARAM NAME="ForeColor" VALUE="2147483661">
<PARAM NAME="BackColor" VALUE="2147483659">
<PARAM NAME="VariousPropertyBits" VALUE="27">
<PARAM NAME="Size" VALUE="2646;397">
<PARAM NAME="MousePointer" VALUE="16">
<PARAM NAME="Min" VALUE="2">
<PARAM NAME="Max" VALUE="40">
<PARAM NAME="Position" VALUE="10">
<PARAM NAME="PrevEnabled" VALUE="1">
<PARAM NAME="NextEnabled" VALUE="1">
<PARAM NAME="SmallChange" VALUE="1">
<PARAM NAME="LargeChange" VALUE="1">
<PARAM NAME="Orientation" VALUE="1">
<PARAM NAME="ProportionalThumb" VALUE="65535">
<PARAM NAME="Delay" VALUE="50">
</OBJECT>
<SCRIPT LANGUAGE="VBScript">
<!--
Dim R
Set R = document.all("saucer")
Sub MyScroll_Change()
objPie.Zoom(MyScroll.Value /10)
End Sub

-->
</SCRIPT>
<hr style="PADDING-RIGHT:0px;PADDING-LEFT:0px;PADDING-BOTTOM:0px;MARGIN:0px;PADDING-TOP:0px;HEIGHT:1px"
size="1">
<div id="result"></div>
</body>
</html>
回复 点赞
passwordgm 2003年08月18日
捧场
回复 点赞
liuruhong 2003年08月18日
VMLPie.prototype.Zoom=function (iValue){
var vX=21600;
var vY=21600;
this.VMLObject=document.all(this.id);
this.VMLObject.coordsize=parseInt(vX / iValue) +","+parseInt(vY /iValue);
var texts=this.VMLObject.getElementsByTagName("TEXTBOX");
for(var i=0;i<texts.length;i++){
if (texts[i].preSize){
texts[i].style.fontSize= parseInt(texts[i].preSize) * iValue +"px";
}
else{
texts[i].style.fontSize= 12 * iValue + "px";
}
}
}

/////////////////////////////////////////////////////////////
//接口功能:
// 添加饼图数据
//参数说明:
// sName:数据标签名称
// sValue:数据值
// sTooltipText:数据描述
///////////////////////////////////////////////////////////////
VMLPie.prototype.AddData=function(sName,sValue,sTooltipText){
var oData=new Object();
oData.Name=sName;
oData.Value=sValue;
oData.TooltipText=sTooltipText;
var iCount=this.all.length;
this.all[iCount]=oData;

}
////////////////////////////////////////////////////////////////
//接口功能:
// 清除所有数据
////////////////////////////////////////////////////////////////
VMLPie.prototype.Clear=function(){
this.all.length=0;
}

function HoverPie(el){
var v_length=500;
var x_cur=Math.cos( el._scale * Math.PI /180);
var y_cur=Math.sin (el._scale * Math.PI /180);
x=parseInt(x_cur * v_length);
y=parseInt(y_cur * v_length);
el.style.top=4000 -y;
el.style.left=1000 +x;
el.strokecolor="black";

}
function RestorePie(el){
el.style.top=4000;
el.style.left=1000;
el.strokecolor="white";

}
function LegendMouseOverEvent(){

var eSrc=window.event.srcElement;
var vPie=document.all(eSrc.element);
HoverPie(vPie);
}
function LegendMouseOutEvent(){
var eSrc=window.event.srcElement;
var vPie=document.all(eSrc.element);
RestorePie(vPie);
}
回复 点赞
liuruhong 2003年08月18日
VMLPie.prototype.CreatePie=function(vGroup){
var mX=Math.pow(2,16) * 360;
//这个参数是划图形的关键
//AE x y width height startangle endangle
//x y表示圆心位置
//width height形状的大小
//startangle endangle的计算方法如下
// 2^16 * 度数

var vTotal=0;
var startAngle=0;
var endAngle=0;
var pieAngle=0;
var prePieAngle=0;

//计算数据的总和
for(i=0;i<this.all.length;i++){
vTotal+=this.all[i].Value;
}
//建立图例容器
//这里子元素的left,top或者width都是针对于容器设置的坐标系统而言的
//例如
//图表容器我设置了coordsize为 21600,21600,那么objLengendGroup的位置都是相对于这个坐标系统而言的
//和实际图形显示的大小没有直接关系
var objLegendGroup=document.createElement("v:group");
with(objLegendGroup){
style.left="17000px";
style.top="4000px";
style.width="4000px";
style.height=1400 * this.all.length +"px";
coordsize="21600,21600";
}
//做图例的背景填充并且设置阴影
var objLegendRect=document.createElement("v:rect");
objLegendRect.fillcolor=" #EBF1F9";
objLegendRect.strokeweight=1;
with(objLegendRect){
//设置为21600,21600,就是保证完全覆盖group客户区
style.width="21600px";
style.height="21600px";
}
//对于图例加入阴影
var vShadow=document.createElement("v:shadow");
vShadow.on="t";
vShadow.type="single";
vShadow.color="graytext";
vShadow.offset="4px,4px";
objLegendRect.appendChild(vShadow);

//将其放到图例的容器中
objLegendGroup.appendChild(objLegendRect);

this.LegendObject=objLegendGroup;
vGroup.appendChild(objLegendGroup);


var strAngle="";
for(i=0;i<this.all.length;i++){ //顺序的划出各个饼图
var vPieEl=document.createElement("v:shape");
var vPieId=document.uniqueID;
vPieEl.style.width="15000px";
vPieEl.style.height="14000px";
vPieEl.style.top="4000px";
vPieEl.style.left="1000px";
vPieEl.adj="0,0";
vPieEl.coordsize="1500,1400";
vPieEl.strokecolor="white";
vPieEl.id=vPieId;
/*
if(i==0){
vPieEl.style.zIndex=100;
}
if(i==(this.all.length -1)){
vPieEl.style.zIndex=101;
}
*/
vPieEl.style.zIndex=1;
vPieEl.onmouseover="HoverPie(this)";
vPieEl.onmouseout="RestorePie(this)";
//vPieEl.style.border="1px solid blue";

pieAngle= this.all[i].Value / vTotal;
startAngle+=prePieAngle;
prePieAngle=pieAngle;
endAngle=pieAngle;

//strAngle+=this.all[i].Name +":" +this.all[i].Value+ " Start:"+startAngle +" End:"+ endAngle +"\n";

vPieEl.path="M 750 700 AE 750 700 750 700 " + parseInt(mX * startAngle) +" " + parseInt(mX * endAngle) +" xe";
vPieEl.title=this.all[i].Name +"\n所占比例:"+ endAngle * 100 +"%\n详细描述:" +this.all[i].TooltipText;
vPieEl._scale=parseInt( 360 * (startAngle + endAngle /2));

var objFill=document.createElement("v:fill");
objFill.rotate="t";
objFill.focus="100%";
objFill.type="gradient";
objFill.angle=parseInt( 360 * (startAngle + endAngle /2));
//vPieEl.appendChild(objFill);
//vPieEl.innerHTML="<v:fill color2='#33cccc' rotate='t' focus='100%' type='gradient'/><v:stroke joinstyle='round'/><o:extrusion v:ext='view' backdepth='50px' on='t' rotationangle='80,-20'/><v:formulas/><v:path o:connecttype='segments'/>";

var objTextbox=document.createElement("v:textbox");
//objTextbox.border="1px solid black";
objTextbox.innerHTML=this.all[i].Name +":" + this.all[i].Value;
objTextbox.inset="5px 5px 5px 5px";
objTextbox.style.width="100px";
objTextbox.style.height="20px";
//vPieEl.appendChild(objTextbox);

var vColor=this.RandColor();
vPieEl.fillcolor=vColor; //设置颜色
//开始画图例
p.innerText=vPieEl.outerHTML;
var colorTip=document.createElement("v:rect");

var iHeight=parseInt(21600 / (this.all.length * 2));
var iWidth=parseInt(iHeight * parseInt(objLegendGroup.style.height) /parseInt(objLegendGroup.style.width) /1.5 );

colorTip.style.height= iHeight;
colorTip.style.width=iWidth;
colorTip.style.top=iHeight * i * 2 + parseInt(iHeight /2);
colorTip.style.left=parseInt(iWidth /2);
colorTip.fillcolor=vColor;
colorTip.element=vPieId;
//colorTip.attachEvent("onmouse",LegendMouseOverEvent);
colorTip.onmouseover="LegendMouseOverEvent()";
colorTip.onmouseout="LegendMouseOutEvent()";

var textTip=document.createElement("v:rect");
textTip.style.top=parseInt(colorTip.style.top)- 500;
textTip.style.left= iWidth * 2;
textTip.innerHTML="<v:textbox style=\"font-size:12px;font-weight:bold\">" + this.all[i].Name +"("+ this.all[i].Value+")</v:textbox>";

objLegendGroup.appendChild(colorTip);
objLegendGroup.appendChild(textTip);

vGroup.appendChild(vPieEl);

}
// result.innerText=objLegendGroup.outerHTML;

}
回复 点赞
liuruhong 2003年08月18日
VMLPie.prototype.CreatePie=function(vGroup){
var mX=Math.pow(2,16) * 360;
//这个参数是划图形的关键
//AE x y width height startangle endangle
//x y表示圆心位置
//width height形状的大小
//startangle endangle的计算方法如下
// 2^16 * 度数

var vTotal=0;
var startAngle=0;
var endAngle=0;
var pieAngle=0;
var prePieAngle=0;

//计算数据的总和
for(i=0;i<this.all.length;i++){
vTotal+=this.all[i].Value;
}
//建立图例容器
//这里子元素的left,top或者width都是针对于容器设置的坐标系统而言的
//例如
//图表容器我设置了coordsize为 21600,21600,那么objLengendGroup的位置都是相对于这个坐标系统而言的
//和实际图形显示的大小没有直接关系
var objLegendGroup=document.createElement("v:group");
with(objLegendGroup){
style.left="17000px";
style.top="4000px";
style.width="4000px";
style.height=1400 * this.all.length +"px";
coordsize="21600,21600";
}
//做图例的背景填充并且设置阴影
var objLegendRect=document.createElement("v:rect");
objLegendRect.fillcolor=" #EBF1F9";
objLegendRect.strokeweight=1;
with(objLegendRect){
//设置为21600,21600,就是保证完全覆盖group客户区
style.width="21600px";
style.height="21600px";
}
//对于图例加入阴影
var vShadow=document.createElement("v:shadow");
vShadow.on="t";
vShadow.type="single";
vShadow.color="graytext";
vShadow.offset="4px,4px";
objLegendRect.appendChild(vShadow);

//将其放到图例的容器中
objLegendGroup.appendChild(objLegendRect);

this.LegendObject=objLegendGroup;
vGroup.appendChild(objLegendGroup);


var strAngle="";
for(i=0;i<this.all.length;i++){ //顺序的划出各个饼图
var vPieEl=document.createElement("v:shape");
var vPieId=document.uniqueID;
vPieEl.style.width="15000px";
vPieEl.style.height="14000px";
vPieEl.style.top="4000px";
vPieEl.style.left="1000px";
vPieEl.adj="0,0";
vPieEl.coordsize="1500,1400";
vPieEl.strokecolor="white";
vPieEl.id=vPieId;
/*
if(i==0){
vPieEl.style.zIndex=100;
}
if(i==(this.all.length -1)){
vPieEl.style.zIndex=101;
}
*/
vPieEl.style.zIndex=1;
vPieEl.onmouseover="HoverPie(this)";
vPieEl.onmouseout="RestorePie(this)";
//vPieEl.style.border="1px solid blue";

pieAngle= this.all[i].Value / vTotal;
startAngle+=prePieAngle;
prePieAngle=pieAngle;
endAngle=pieAngle;

//strAngle+=this.all[i].Name +":" +this.all[i].Value+ " Start:"+startAngle +" End:"+ endAngle +"\n";

vPieEl.path="M 750 700 AE 750 700 750 700 " + parseInt(mX * startAngle) +" " + parseInt(mX * endAngle) +" xe";
vPieEl.title=this.all[i].Name +"\n所占比例:"+ endAngle * 100 +"%\n详细描述:" +this.all[i].TooltipText;
vPieEl._scale=parseInt( 360 * (startAngle + endAngle /2));

var objFill=document.createElement("v:fill");
objFill.rotate="t";
objFill.focus="100%";
objFill.type="gradient";
objFill.angle=parseInt( 360 * (startAngle + endAngle /2));
//vPieEl.appendChild(objFill);
//vPieEl.innerHTML="<v:fill color2='#33cccc' rotate='t' focus='100%' type='gradient'/><v:stroke joinstyle='round'/><o:extrusion v:ext='view' backdepth='50px' on='t' rotationangle='80,-20'/><v:formulas/><v:path o:connecttype='segments'/>";

var objTextbox=document.createElement("v:textbox");
//objTextbox.border="1px solid black";
objTextbox.innerHTML=this.all[i].Name +":" + this.all[i].Value;
objTextbox.inset="5px 5px 5px 5px";
objTextbox.style.width="100px";
objTextbox.style.height="20px";
//vPieEl.appendChild(objTextbox);

var vColor=this.RandColor();
vPieEl.fillcolor=vColor; //设置颜色
//开始画图例
p.innerText=vPieEl.outerHTML;
var colorTip=document.createElement("v:rect");

var iHeight=parseInt(21600 / (this.all.length * 2));
var iWidth=parseInt(iHeight * parseInt(objLegendGroup.style.height) /parseInt(objLegendGroup.style.width) /1.5 );

colorTip.style.height= iHeight;
colorTip.style.width=iWidth;
colorTip.style.top=iHeight * i * 2 + parseInt(iHeight /2);
colorTip.style.left=parseInt(iWidth /2);
colorTip.fillcolor=vColor;
colorTip.element=vPieId;
//colorTip.attachEvent("onmouse",LegendMouseOverEvent);
colorTip.onmouseover="LegendMouseOverEvent()";
colorTip.onmouseout="LegendMouseOutEvent()";

var textTip=document.createElement("v:rect");
textTip.style.top=parseInt(colorTip.style.top)- 500;
textTip.style.left= iWidth * 2;
textTip.innerHTML="<v:textbox style=\"font-size:12px;font-weight:bold\">" + this.all[i].Name +"("+ this.all[i].Value+")</v:textbox>";

objLegendGroup.appendChild(colorTip);
objLegendGroup.appendChild(textTip);

vGroup.appendChild(vPieEl);

}
// result.innerText=objLegendGroup.outerHTML;

}
///////////////////////////////////////////////////////////////////////
//接口功能:
// 放大或者缩小图形
//参数说明:
// iValue:放大的或者缩小的倍数,1为原图大小,0.5原图的50%,2为原图的
// 两倍,以此类推
/////////////////////////////////////////////////////////////////////////
VMLPie.prototype.Zoom=function (iValue){
var vX=21600;
var vY=21600;
this.VMLObject=document.all(this.id);
this.VMLObject.coordsize=parseInt(vX / iValue) +","+parseInt(vY /iValue);
var texts=this.VMLObject.getElementsByTagName("TEXTBOX");
for(var i=0;i<texts.length;i++){
if (texts[i].preSize){
texts[i].style.fontSize= parseInt(texts[i].preSize) * iValue +"px";
}
else{
texts[i].style.fontSize= 12 * iValue + "px";
}
}
}
回复 点赞
发动态
发帖子
JavaScript
创建于2007-09-28

5.1w+

社区成员

22.3w+

社区内容

Web 开发 JavaScript
社区公告
暂无公告