


/*****************************************************************************************************************
*版本:2D或者3D饼状统计图
*日期:2010.2.12
*作者:孙晓玮
*联系方式:454084563@qq.com
*说明:用VML实现饼状统计图
*bug:cake上升时的距离以及backdepth是不变的,设置的高宽太小或者太大,效果会不太好
*2D饼图与图例的互动问题
*****************************************************************************************************************/
var Stop1;
//函数作用:3dcake升起
//参数含义:cakeID,图例ID
function moveover3D(item,rec){
var item1=document.getElementById(item);
var rec1=document.getElementById(rec);
var position=parseInt(item1.style.top);
rec1.style.display = "";
if(position>-970){
item1.style.top=position-80;
Stop1=setTimeout("moveover3D(\""+item+"\",\""+rec+"\")",10)
}else{
return;
}
}
//函数作用:3dcake落下
//参数含义:cakeID,图例ID
function moveout3D(item,rec)
{
var item1=document.getElementById(item);
var rec1=document.getElementById(rec);
clearTimeout(Stop1);
item1.style.top=-250;
rec1.style.display = "none";
}
var Stop2;
var Num = 0;
//函数作用:2dcake弹出
//参数含义:cakeID,图例ID
function moveover2D(item,rec,midangle){
var item1=document.getElementById(item);
var rec1=document.getElementById(rec);
rec1.style.display = "";
if (Num<10) {
var length=50;
var xcur=Math.cos(midangle * Math.PI /180);
var ycur=Math.sin(midangle * Math.PI /180);
x=parseInt(xcur * length);
y=parseInt(ycur * length);
item1.style.top=1850 - Num*y;
item1.style.left=3825 + Num*x;
Stop2=setTimeout("moveover2D(\""+item+"\",\""+rec+"\",\""+midangle+"\")",10);
Num++;
}
}
//函数作用:2dcake弹回
//参数含义:cakeID,图例ID
function moveout2D(item,rec)
{
var item1=document.getElementById(item);
var rec1=document.getElementById(rec);
rec1.style.display = "none";
clearTimeout(Stop2);
Num = 0;
item1.style.top=1850;
item1.style.left=3825;
}
//////////////////////////////////////////////////////////////////////////////////
//函数作用:3D饼图类
//参数含义:父控件ID,宽,高,标题,数据数组,显示单位//建议宽高比5:3,也可随意设置
//pCakes二维数组有name,qty,color,颜色若设置null使用默认色表
//////////////////////////////////////////////////////////////////////////////////
function DrawPieChart(pContainer,pWidth,pHeight,pCakes,pCaption,pUnit,pType)//pCakes结构为(name ,value)
{
var container=document.getElementById(pContainer);
container.style.width=pWidth;
container.style.height=pHeight;
//添加背景
var background=document.createElement("<v:rect style='position:absolute;left:1px;top:1px;width:"+pWidth+"px;height:"+pHeight+"px;' fillcolor='#EFEFEF' strokecolor='gray'></v:rect>");
var shadow = document.createElement("<v:shadow on='t' type='single' color='silver' offset='4pt,4pt'/>");
background.appendChild(shadow);
container.appendChild(background);
var percent=new Array();
var total=0;
var defaultColor=new Array("#FF0000","#663366","#990099","#3300CC","33CCFF","#FF6600","#FFCC00","#CC33CC","#33CCCC","#33FF33","#CCFF66","009933","996600","#FF66FF","#003300","#Yellow","#Lime","Navy","#Blue");
for(var i=0;i<pCakes.length;i++){
total+=pCakes[i][1];
}
for(i=0;i<pCakes.length;i++)
{
percent[i]=pCakes[i][1]/total;
if (pCakes[i][2]==null)
{
pCakes[i][2] = defaultColor[(i%defaultColor.length)];
}
}
//创建画布///////////////////////////////////////////////////////////
var canvas=document.createElement("v:group");
canvas.style.position='absolute';
canvas.style.top='0px';
canvas.style.left='0px';
canvas.style.width=pWidth;
canvas.style.height=pHeight;
canvas.coordsize='21000,11500';
//大标题///////////////////////////////////////////////////////////
var caption=document.createElement("v:rect");
caption.style.position='relative';
caption.style.top='50px';
caption.style.left='550px';
caption.style.width='20000px';
caption.style.height='800px';
caption.fillcolor='#EFEFEF';
caption.stroked='false';
var captiontext=document.createElement("v:TextBox");
captiontext.inset='0pt,0pt,0pt,0pt';
var captiondiv = document.createElement("<div style='FONT-SIZE:20px;COLOR:#6633FF;WORD-BREAK;FONT-FAMILY:黑体;vertical-align:middle; text-align:center;'></div>");
captiondiv.innerHTML = pCaption;
captiontext.appendChild(captiondiv);
caption.appendChild(captiontext);
//作图区///////////////////////////////////////////////////////////
var drawSection=document.createElement("v:rect");
drawSection.style.position='relative';
drawSection.style.top=parseInt(caption.style.top)+parseInt(caption.style.height)+'px';
drawSection.style.left='550px';
drawSection.style.width='20000px';
drawSection.style.height='10000px';
drawSection.strokecolor='#888';
drawSection.fillcolor='#9fc';
drawSection.appendChild(document.createElement("<v:fill rotate='t' angle='-45' focus='100%' type='gradient'/>"));
//计算每个图例元素的高度///////////////////////////////////////////////////////////
var defaultHeight = 750;
var topx;
var dx = 20;//元素距离
if(pCakes.length*defaultHeight>8050)//如果超过图例高度,重新计算每个图例元素的高度
defaultHeight = parseInt((8050-(pCakes.length-1)*20)/pCakes.length);
//图例区域///////////////////////////////////////////////////////////
var legendArea=document.createElement("v:rect");
legendArea.style.position='relative';
legendArea.style.top='1350px';
legendArea.style.left='15000px';
legendArea.style.width='5000px';
legendArea.style.height=pCakes.length*defaultHeight+(pCakes.length-1)*dx+950;
legendArea.fillcolor='#9cf';
legendArea.stroked='t';
legendArea.strokecolor='#09f';
legendArea.appendChild(document.createElement("<v:fill rotate='t' angle='-175' focus='100%' type='gradient'/>"));
legendArea.appendChild(document.createElement("<v:shadow on='t' type='single' color='silver' offset='1pt,1pt'/>"));
//图例标题///////////////////////////////////////////////////////////
var legendTitle=document.createElement("v:rect");
legendTitle.style.position='relative';
legendTitle.style.top='1500px';
legendTitle.style.left='15200px';
legendTitle.style.width='4300px';
legendTitle.style.height='650px';
legendTitle.filled='f';
legendTitle.stroked='f';
legendTitle.strokecolor='#000';
var tb = document.createElement("<v:TextBox inset='2pt,0pt,0pt,0pt' style='FONT-SIZE:10pt;COLOR:#6633FF;'></v:TextBox>");
var tbdiv = document.createElement("<div style='align:left'></div>");
tbdiv.innerHTML = "Total:"+xRound(total,2)+"("+pUnit+")";
tb.appendChild(tbdiv);
legendTitle.appendChild(tb);
//添加到画布///////////////////////////////////////////////////////////
canvas.appendChild(caption);
canvas.appendChild(drawSection);
canvas.appendChild(legendArea);
canvas.appendChild(legendTitle);
//绘制图例///////////////////////////////////////////////////////////
for(var i=0;i<pCakes.length;i++)
{
topx=2150+i*(defaultHeight+dx);
//图例高亮区域///////////////////////////////////////////////////////////
var legendBg=document.createElement("v:rect");
legendBg.id=pContainer+'rec'+(i+1);
legendBg.style.position='relative';
legendBg.style.top=topx+'px';
legendBg.style.display='none';
legendBg.style.left='15200px';
legendBg.style.width='4300px';
legendBg.style.height=defaultHeight;
legendBg.fillcolor='#efefef';
legendBg.strokecolor=pCakes[i][2];
legendBg.appendChild(document.createElement("<v:fill opacity='.6' color2='fill darken(118)' o:opacity2='.6' rotate='t' method='linear sigma' focus='100%' type='gradient'/>"));
//图例元素///////////////////////////////////////////////////////////
var legendElement=document.createElement("v:rect");
legendElement.style.position='relative';
legendElement.style.top=topx+'px';
legendElement.style.left='15200px';
legendElement.style.width='1000px';
legendElement.style.height=defaultHeight;
legendElement.fillcolor=pCakes[i][2];
legendElement.stroked='f';
//图例汉字区域///////////////////////////////////////////////////////////
var legendTxt=document.createElement("v:rect");
legendTxt.style.position='relative';
legendTxt.style.top=topx+'px';
legendTxt.style.left='16300px';
legendTxt.style.width='3400px';
legendTxt.style.height=defaultHeight;
legendTxt.filled='f';
legendTxt.stroked='f';
var mouseAction;
if(pType=="3D")
mouseAction = "onmouseover='moveover3D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\")'onmouseout='moveout3D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\")'";
//else
// mouseAction = "onmouseover='moveover2D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\",\""+parseInt(360*(startAngle+endAngle/2))+"\")' onmouseout='moveout2D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\")'";
var tb1 = document.createElement("<v:TextBox inset='0pt,0pt,0pt,0pt' style='FONT-SIZE:9pt;COLOR:#6633FF;cursor:hand;'"+mouseAction+"></v:TextBox>");
var tbdiv1 = document.createElement("<div align='left'></div>");
tbdiv1.innerHTML = pCakes[i][0]+": "+xRound(pCakes[i][1],2);
tb1.appendChild(tbdiv1);
legendTxt.appendChild(tb1);
//添加到画布///////////////////////////////////////////////////////////
canvas.appendChild(legendBg);
canvas.appendChild(legendElement);
canvas.appendChild(legendTxt);
}
//画cake//////////////////////////////////////////////////////////
/*****************************************************************************************
设置Path,这个也就是比较令人难以看懂的部分了,我首先求出了startAngle和endAngle,startAngle的意义是这样的,
假设有3个数,0.2,0.2,0.4,对于第二项来说,startAngle应该是 0.25,endAngle是0.25,对于第三项来说,startAngle是0.5,
endAngle是0.5,总而言之,startAngle可以表示为前面数据所占的比例,engAngle表示当前数据所占的比例。Path有很多指令,
对于其他指令,我就不多作解释,而这里使用的是M 10800 10800 AE 10800 10800 10800 10800 start end 。对于shape我重新定义了
coordsize=21600,21600, m 10800 10800则表示移动到 10800 10800,就是移动到shape定义的中心,AE用来画曲线,总共有6个参数,
w3c的note描述如下center (x,y) size(w,h) start-angle, end-angle,前面四个参数不难理解,
剩下的两个参数我不是特别明白意思,但是在国外的一篇文章看到其中的算法如下应该是 2^16 * 度数,
对应于程序,就应该是startAngle * 2^16 * 360,因为我的startAngle是比例。
******************************************************************************************/
var startAngle=0.25; //默认起始点为3点位置, +0.25使起始点变为12点位置,就可以设置每隔cake的zIndex,才能以正常效果显示
var pieAngle=0;
var prePieAngle=0;
var mX=Math.pow(2,16)*360;
var zIndex = 10;
if (pType=="3D")//画3D饼图
{
for(i=0;i<pCakes.length;i++)
{
pieAngle = percent[i];
startAngle+=prePieAngle;
prePieAngle=pieAngle;
if (startAngle>=0.75) {//这里根据每个cake位置设置其zindex
zIndex-- ;
}
var cake=document.createElement("<v:shape coordsize='21600,21600' o:spt='95' title='"+pCakes[i][0]+": "+xRound(percent[i]*100,2)+"%' id='"+pContainer+"cake"+(i+1)+
"'style='position:relative;left:1875px;top:-250px;WIDTH:12000px;HEIGHT:12000px;z-index:"+zIndex+
"'fillcolor='"+pCakes[i][2]+
"'path='m 10800 10800 ae 10800 10800 10800 10800 "+parseInt(mX*startAngle)+" "+parseInt(mX*pieAngle)+" xe'"+
"' onmouseover='moveover3D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\")' onmouseout='moveout3D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\")'>"+
"</v:shape>");
cake.style.cursor='hand';
cake.innerHTML= "<v:fill opacity='60293f' color2='fill lighten(120)' o:opacity2='60293f' rotate='t' angle='-135' method='linear sigma' focus='100%' type='gradient'/>"+
"<o:extrusion v:ext='view' on='t' backdepth='16' rotationangle='60' viewpoint='0,0'viewpointorigin='0,0' skewamt='0' lightposition='-50000,-50000' lightposition2='50000'/>";
canvas.appendChild(cake);
}
}
else if(pType=="2D")//画2D饼图
{
for(i=0;i<pCakes.length;i++)
{
pieAngle = percent[i]; //所占百分比
startAngle+=prePieAngle; //当前cake的起始角度
prePieAngle=pieAngle;
if (startAngle>=0.75) {
zIndex-- ;
} //pCakes[i][0]xRound(percent[i]*100,2)
var cake=document.createElement("<v:shape coordsize='21600,21600' o:spt='95' title='"+pCakes[i][0]+": "+xRound(percent[i]*100,2)+"%' id='"+pContainer+"cake"+(i+1)+
"'style='position:relative;left:3825px;top:1850px;WIDTH:8000px;HEIGHT:8000px;z-index:"+zIndex+
"'fillcolor='"+pCakes[i][2]+
"'path='m 10800 10800 ae 10800 10800 10800 10800 "+parseInt(mX*startAngle)+" "+parseInt(mX*pieAngle)+" xe'"+
"' onmouseover='moveover2D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\",\""+parseInt(360*(startAngle+pieAngle/2))+"\")' onmouseout='moveout2D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\")'>"+
"</v:shape>");
cake.style.cursor='hand';
cake.innerHTML= "<v:fill opacity='60293f' color2='fill lighten(120)' o:opacity2='60293f' rotate='t' angle='-135' method='linear sigma' focus='100%' type='gradient'/>"+
"<o:extrusion v:ext='view' on='t' backdepth='0' rotationangle='0' viewpoint='0,0'viewpointorigin='0,0' skewamt='0' lightposition='-50000,-50000' lightposition2='50000'/>";
canvas.appendChild(cake);
}
}
container.appendChild(canvas);
}
//函数作用:数值格式化
//参数含义:待格式化数字,小数保留位数
function xRound(num,n)
{
num = Math.round (num*Math.pow(10,n))/Math.pow(10,n);
return num;
}
*版本:2D或者3D饼状统计图
*日期:2010.2.12
*作者:孙晓玮
*联系方式:454084563@qq.com
*说明:用VML实现饼状统计图
*bug:cake上升时的距离以及backdepth是不变的,设置的高宽太小或者太大,效果会不太好
*2D饼图与图例的互动问题
*****************************************************************************************************************/
var Stop1;
//函数作用:3dcake升起
//参数含义:cakeID,图例ID
function moveover3D(item,rec){
var item1=document.getElementById(item);
var rec1=document.getElementById(rec);
var position=parseInt(item1.style.top);
rec1.style.display = "";
if(position>-970){
item1.style.top=position-80;
Stop1=setTimeout("moveover3D(\""+item+"\",\""+rec+"\")",10)
}else{
return;
}
}
//函数作用:3dcake落下
//参数含义:cakeID,图例ID
function moveout3D(item,rec)
{
var item1=document.getElementById(item);
var rec1=document.getElementById(rec);
clearTimeout(Stop1);
item1.style.top=-250;
rec1.style.display = "none";
}
var Stop2;
var Num = 0;
//函数作用:2dcake弹出
//参数含义:cakeID,图例ID
function moveover2D(item,rec,midangle){
var item1=document.getElementById(item);
var rec1=document.getElementById(rec);
rec1.style.display = "";
if (Num<10) {
var length=50;
var xcur=Math.cos(midangle * Math.PI /180);
var ycur=Math.sin(midangle * Math.PI /180);
x=parseInt(xcur * length);
y=parseInt(ycur * length);
item1.style.top=1850 - Num*y;
item1.style.left=3825 + Num*x;
Stop2=setTimeout("moveover2D(\""+item+"\",\""+rec+"\",\""+midangle+"\")",10);
Num++;
}
}
//函数作用:2dcake弹回
//参数含义:cakeID,图例ID
function moveout2D(item,rec)
{
var item1=document.getElementById(item);
var rec1=document.getElementById(rec);
rec1.style.display = "none";
clearTimeout(Stop2);
Num = 0;
item1.style.top=1850;
item1.style.left=3825;
}
//////////////////////////////////////////////////////////////////////////////////
//函数作用:3D饼图类
//参数含义:父控件ID,宽,高,标题,数据数组,显示单位//建议宽高比5:3,也可随意设置
//pCakes二维数组有name,qty,color,颜色若设置null使用默认色表
//////////////////////////////////////////////////////////////////////////////////
function DrawPieChart(pContainer,pWidth,pHeight,pCakes,pCaption,pUnit,pType)//pCakes结构为(name ,value)
{
var container=document.getElementById(pContainer);
container.style.width=pWidth;
container.style.height=pHeight;
//添加背景
var background=document.createElement("<v:rect style='position:absolute;left:1px;top:1px;width:"+pWidth+"px;height:"+pHeight+"px;' fillcolor='#EFEFEF' strokecolor='gray'></v:rect>");
var shadow = document.createElement("<v:shadow on='t' type='single' color='silver' offset='4pt,4pt'/>");
background.appendChild(shadow);
container.appendChild(background);
var percent=new Array();
var total=0;
var defaultColor=new Array("#FF0000","#663366","#990099","#3300CC","33CCFF","#FF6600","#FFCC00","#CC33CC","#33CCCC","#33FF33","#CCFF66","009933","996600","#FF66FF","#003300","#Yellow","#Lime","Navy","#Blue");
for(var i=0;i<pCakes.length;i++){
total+=pCakes[i][1];
}
for(i=0;i<pCakes.length;i++)
{
percent[i]=pCakes[i][1]/total;
if (pCakes[i][2]==null)
{
pCakes[i][2] = defaultColor[(i%defaultColor.length)];
}
}
//创建画布///////////////////////////////////////////////////////////
var canvas=document.createElement("v:group");
canvas.style.position='absolute';
canvas.style.top='0px';
canvas.style.left='0px';
canvas.style.width=pWidth;
canvas.style.height=pHeight;
canvas.coordsize='21000,11500';
//大标题///////////////////////////////////////////////////////////
var caption=document.createElement("v:rect");
caption.style.position='relative';
caption.style.top='50px';
caption.style.left='550px';
caption.style.width='20000px';
caption.style.height='800px';
caption.fillcolor='#EFEFEF';
caption.stroked='false';
var captiontext=document.createElement("v:TextBox");
captiontext.inset='0pt,0pt,0pt,0pt';
var captiondiv = document.createElement("<div style='FONT-SIZE:20px;COLOR:#6633FF;WORD-BREAK;FONT-FAMILY:黑体;vertical-align:middle; text-align:center;'></div>");
captiondiv.innerHTML = pCaption;
captiontext.appendChild(captiondiv);
caption.appendChild(captiontext);
//作图区///////////////////////////////////////////////////////////
var drawSection=document.createElement("v:rect");
drawSection.style.position='relative';
drawSection.style.top=parseInt(caption.style.top)+parseInt(caption.style.height)+'px';
drawSection.style.left='550px';
drawSection.style.width='20000px';
drawSection.style.height='10000px';
drawSection.strokecolor='#888';
drawSection.fillcolor='#9fc';
drawSection.appendChild(document.createElement("<v:fill rotate='t' angle='-45' focus='100%' type='gradient'/>"));
//计算每个图例元素的高度///////////////////////////////////////////////////////////
var defaultHeight = 750;
var topx;
var dx = 20;//元素距离
if(pCakes.length*defaultHeight>8050)//如果超过图例高度,重新计算每个图例元素的高度
defaultHeight = parseInt((8050-(pCakes.length-1)*20)/pCakes.length);
//图例区域///////////////////////////////////////////////////////////
var legendArea=document.createElement("v:rect");
legendArea.style.position='relative';
legendArea.style.top='1350px';
legendArea.style.left='15000px';
legendArea.style.width='5000px';
legendArea.style.height=pCakes.length*defaultHeight+(pCakes.length-1)*dx+950;
legendArea.fillcolor='#9cf';
legendArea.stroked='t';
legendArea.strokecolor='#09f';
legendArea.appendChild(document.createElement("<v:fill rotate='t' angle='-175' focus='100%' type='gradient'/>"));
legendArea.appendChild(document.createElement("<v:shadow on='t' type='single' color='silver' offset='1pt,1pt'/>"));
//图例标题///////////////////////////////////////////////////////////
var legendTitle=document.createElement("v:rect");
legendTitle.style.position='relative';
legendTitle.style.top='1500px';
legendTitle.style.left='15200px';
legendTitle.style.width='4300px';
legendTitle.style.height='650px';
legendTitle.filled='f';
legendTitle.stroked='f';
legendTitle.strokecolor='#000';
var tb = document.createElement("<v:TextBox inset='2pt,0pt,0pt,0pt' style='FONT-SIZE:10pt;COLOR:#6633FF;'></v:TextBox>");
var tbdiv = document.createElement("<div style='align:left'></div>");
tbdiv.innerHTML = "Total:"+xRound(total,2)+"("+pUnit+")";
tb.appendChild(tbdiv);
legendTitle.appendChild(tb);
//添加到画布///////////////////////////////////////////////////////////
canvas.appendChild(caption);
canvas.appendChild(drawSection);
canvas.appendChild(legendArea);
canvas.appendChild(legendTitle);
//绘制图例///////////////////////////////////////////////////////////
for(var i=0;i<pCakes.length;i++)
{
topx=2150+i*(defaultHeight+dx);
//图例高亮区域///////////////////////////////////////////////////////////
var legendBg=document.createElement("v:rect");
legendBg.id=pContainer+'rec'+(i+1);
legendBg.style.position='relative';
legendBg.style.top=topx+'px';
legendBg.style.display='none';
legendBg.style.left='15200px';
legendBg.style.width='4300px';
legendBg.style.height=defaultHeight;
legendBg.fillcolor='#efefef';
legendBg.strokecolor=pCakes[i][2];
legendBg.appendChild(document.createElement("<v:fill opacity='.6' color2='fill darken(118)' o:opacity2='.6' rotate='t' method='linear sigma' focus='100%' type='gradient'/>"));
//图例元素///////////////////////////////////////////////////////////
var legendElement=document.createElement("v:rect");
legendElement.style.position='relative';
legendElement.style.top=topx+'px';
legendElement.style.left='15200px';
legendElement.style.width='1000px';
legendElement.style.height=defaultHeight;
legendElement.fillcolor=pCakes[i][2];
legendElement.stroked='f';
//图例汉字区域///////////////////////////////////////////////////////////
var legendTxt=document.createElement("v:rect");
legendTxt.style.position='relative';
legendTxt.style.top=topx+'px';
legendTxt.style.left='16300px';
legendTxt.style.width='3400px';
legendTxt.style.height=defaultHeight;
legendTxt.filled='f';
legendTxt.stroked='f';
var mouseAction;
if(pType=="3D")
mouseAction = "onmouseover='moveover3D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\")'onmouseout='moveout3D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\")'";
//else
// mouseAction = "onmouseover='moveover2D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\",\""+parseInt(360*(startAngle+endAngle/2))+"\")' onmouseout='moveout2D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\")'";
var tb1 = document.createElement("<v:TextBox inset='0pt,0pt,0pt,0pt' style='FONT-SIZE:9pt;COLOR:#6633FF;cursor:hand;'"+mouseAction+"></v:TextBox>");
var tbdiv1 = document.createElement("<div align='left'></div>");
tbdiv1.innerHTML = pCakes[i][0]+": "+xRound(pCakes[i][1],2);
tb1.appendChild(tbdiv1);
legendTxt.appendChild(tb1);
//添加到画布///////////////////////////////////////////////////////////
canvas.appendChild(legendBg);
canvas.appendChild(legendElement);
canvas.appendChild(legendTxt);
}
//画cake//////////////////////////////////////////////////////////
/*****************************************************************************************
设置Path,这个也就是比较令人难以看懂的部分了,我首先求出了startAngle和endAngle,startAngle的意义是这样的,
假设有3个数,0.2,0.2,0.4,对于第二项来说,startAngle应该是 0.25,endAngle是0.25,对于第三项来说,startAngle是0.5,
endAngle是0.5,总而言之,startAngle可以表示为前面数据所占的比例,engAngle表示当前数据所占的比例。Path有很多指令,
对于其他指令,我就不多作解释,而这里使用的是M 10800 10800 AE 10800 10800 10800 10800 start end 。对于shape我重新定义了
coordsize=21600,21600, m 10800 10800则表示移动到 10800 10800,就是移动到shape定义的中心,AE用来画曲线,总共有6个参数,
w3c的note描述如下center (x,y) size(w,h) start-angle, end-angle,前面四个参数不难理解,
剩下的两个参数我不是特别明白意思,但是在国外的一篇文章看到其中的算法如下应该是 2^16 * 度数,
对应于程序,就应该是startAngle * 2^16 * 360,因为我的startAngle是比例。
******************************************************************************************/
var startAngle=0.25; //默认起始点为3点位置, +0.25使起始点变为12点位置,就可以设置每隔cake的zIndex,才能以正常效果显示
var pieAngle=0;
var prePieAngle=0;
var mX=Math.pow(2,16)*360;
var zIndex = 10;
if (pType=="3D")//画3D饼图
{
for(i=0;i<pCakes.length;i++)
{
pieAngle = percent[i];
startAngle+=prePieAngle;
prePieAngle=pieAngle;
if (startAngle>=0.75) {//这里根据每个cake位置设置其zindex
zIndex-- ;
}
var cake=document.createElement("<v:shape coordsize='21600,21600' o:spt='95' title='"+pCakes[i][0]+": "+xRound(percent[i]*100,2)+"%' id='"+pContainer+"cake"+(i+1)+
"'style='position:relative;left:1875px;top:-250px;WIDTH:12000px;HEIGHT:12000px;z-index:"+zIndex+
"'fillcolor='"+pCakes[i][2]+
"'path='m 10800 10800 ae 10800 10800 10800 10800 "+parseInt(mX*startAngle)+" "+parseInt(mX*pieAngle)+" xe'"+
"' onmouseover='moveover3D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\")' onmouseout='moveout3D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\")'>"+
"</v:shape>");
cake.style.cursor='hand';
cake.innerHTML= "<v:fill opacity='60293f' color2='fill lighten(120)' o:opacity2='60293f' rotate='t' angle='-135' method='linear sigma' focus='100%' type='gradient'/>"+
"<o:extrusion v:ext='view' on='t' backdepth='16' rotationangle='60' viewpoint='0,0'viewpointorigin='0,0' skewamt='0' lightposition='-50000,-50000' lightposition2='50000'/>";
canvas.appendChild(cake);
}
}
else if(pType=="2D")//画2D饼图
{
for(i=0;i<pCakes.length;i++)
{
pieAngle = percent[i]; //所占百分比
startAngle+=prePieAngle; //当前cake的起始角度
prePieAngle=pieAngle;
if (startAngle>=0.75) {
zIndex-- ;
} //pCakes[i][0]xRound(percent[i]*100,2)
var cake=document.createElement("<v:shape coordsize='21600,21600' o:spt='95' title='"+pCakes[i][0]+": "+xRound(percent[i]*100,2)+"%' id='"+pContainer+"cake"+(i+1)+
"'style='position:relative;left:3825px;top:1850px;WIDTH:8000px;HEIGHT:8000px;z-index:"+zIndex+
"'fillcolor='"+pCakes[i][2]+
"'path='m 10800 10800 ae 10800 10800 10800 10800 "+parseInt(mX*startAngle)+" "+parseInt(mX*pieAngle)+" xe'"+
"' onmouseover='moveover2D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\",\""+parseInt(360*(startAngle+pieAngle/2))+"\")' onmouseout='moveout2D(\""+pContainer+"cake"+(i+1)+"\",\""+pContainer+"rec"+(i+1)+"\")'>"+
"</v:shape>");
cake.style.cursor='hand';
cake.innerHTML= "<v:fill opacity='60293f' color2='fill lighten(120)' o:opacity2='60293f' rotate='t' angle='-135' method='linear sigma' focus='100%' type='gradient'/>"+
"<o:extrusion v:ext='view' on='t' backdepth='0' rotationangle='0' viewpoint='0,0'viewpointorigin='0,0' skewamt='0' lightposition='-50000,-50000' lightposition2='50000'/>";
canvas.appendChild(cake);
}
}
container.appendChild(canvas);
}
//函数作用:数值格式化
//参数含义:待格式化数字,小数保留位数
function xRound(num,n)
{
num = Math.round (num*Math.pow(10,n))/Math.pow(10,n);
return num;
}
一些原理啊 也是根据网上高手研究透的,然后基于他们的修改的, 加入了自己的想法。 具体不多说,自己研究吧。2dcake鼠标联动效果没加上,懒得搞了。
下面是使用方法

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="HistoryStatistic.aspx.cs" Inherits="VmlProject.HistoryStatistic" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
<head id="Head1" runat="server">
<style type="text/css">
v\:*
{
behavior: url(#default#VML);
}
o\:*
{
behavior: url(#default#VML);
}
body
{
font-family: arial;
}
</style>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>无标题页</title>
<script src="js/jquery.js" type="text/javascript"></script>
<script src="js/PieChart.js" type="text/javascript"></script>
<script src="js/RectChart3D.js" type="text/javascript"></script>
<script src="js/RectChart.js" type="text/javascript"></script>
</head>
<body>
<form id="form1" runat="server">
<div>
<div id="div1" style="position:relative; float:left;"></div>
<div id="div2" style="position:relative; float:left;margin-left:10px;"></div>
<div id="div3" style="position:relative; margin-top:10px; float:left; width:500px; height:300px;"></div>
<div id="div4" style="position:relative; float:left;margin-top:10px; margin-left:10px;"></div>
</div>
<script language="javascript" type="text/javascript">
var pData = new Array();
for(i=0;i<10;i++)
{
var oData=new Object();
oData[0]=i*100;
oData[1]=Math.random()*10;
pData[i]=oData;
}
DrawPieChart("div1",500,300,pData,"3D饼图","元","3D");
DrawPieChart("div2",500,300,pData,"2D饼图","元","2D");
DrawRectChart("div4",pData,500,300,"2D柱图", "天", "元","2D")
//////////////////////////////////////////////////////////
pData = new Array();
var oData;
for(i=0;i<16;i++)
{
oData=new Object();
oData[0]=i;
oData[1]=i*3;
oData[2]=i*6;
oData[3]=i*2;
oData[4]=i*4;
pData[i]=oData;
}
var aaa = new RectChart3D('div3',500,300,null,false,null);
aaa.SetCaptionAtt('实时监测柱状图',null,null);
aaa.SetxAxisAtt('时间',null,null,null,null);
aaa.SetyAxisAtt(0,100,2,'值',null,null,null,6,null);
aaa.SetData(pData,pData,5,oData);
aaa.Draw();
aaa.AddRect();
</script>
</form>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
<head id="Head1" runat="server">
<style type="text/css">
v\:*
{
behavior: url(#default#VML);
}
o\:*
{
behavior: url(#default#VML);
}
body
{
font-family: arial;
}
</style>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>无标题页</title>
<script src="js/jquery.js" type="text/javascript"></script>
<script src="js/PieChart.js" type="text/javascript"></script>
<script src="js/RectChart3D.js" type="text/javascript"></script>
<script src="js/RectChart.js" type="text/javascript"></script>
</head>
<body>
<form id="form1" runat="server">
<div>
<div id="div1" style="position:relative; float:left;"></div>
<div id="div2" style="position:relative; float:left;margin-left:10px;"></div>
<div id="div3" style="position:relative; margin-top:10px; float:left; width:500px; height:300px;"></div>
<div id="div4" style="position:relative; float:left;margin-top:10px; margin-left:10px;"></div>
</div>
<script language="javascript" type="text/javascript">
var pData = new Array();
for(i=0;i<10;i++)
{
var oData=new Object();
oData[0]=i*100;
oData[1]=Math.random()*10;
pData[i]=oData;
}
DrawPieChart("div1",500,300,pData,"3D饼图","元","3D");
DrawPieChart("div2",500,300,pData,"2D饼图","元","2D");
DrawRectChart("div4",pData,500,300,"2D柱图", "天", "元","2D")
//////////////////////////////////////////////////////////
pData = new Array();
var oData;
for(i=0;i<16;i++)
{
oData=new Object();
oData[0]=i;
oData[1]=i*3;
oData[2]=i*6;
oData[3]=i*2;
oData[4]=i*4;
pData[i]=oData;
}
var aaa = new RectChart3D('div3',500,300,null,false,null);
aaa.SetCaptionAtt('实时监测柱状图',null,null);
aaa.SetxAxisAtt('时间',null,null,null,null);
aaa.SetyAxisAtt(0,100,2,'值',null,null,null,6,null);
aaa.SetData(pData,pData,5,oData);
aaa.Draw();
aaa.AddRect();
</script>
</form>
</body>
</html>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理