| 本文代码是基于beta2研发 越来越多的web应用需要使用图表来进行数据显示和分析。例如:投票结果显示,公司生产情况统计图显示分析等等。利用图表来显示数据,具备直观,清楚等长处。 传统的asp技术是不支持画图表的,那么就不得不利用active x或java applets来实现这个功能。新近出现的asp解决了这个问题,只要利用asp中关于图像显示的类,就能够画出丰富,动态的图表(如图1)。本文将要讲述如何利用asp技术结合ado技术画条形图和饼图。 图1 首先建立一个c#的类库。 打开vs,建立一个名为insight_cs.webcharts新的类库工程,将解决方案的名称改为insight,将class.cs文档名改为insight_cs.webcharts.cs,最后打开insight_cs.webcharts.cs文档。其中代码如下: /*自定义类,通过输入不同的参数,这些类能够画不同的图像 */ using system; using system.io;//用于文档存取 using system.data;//用于数据访问 using system.drawing;//提供画gdi+图像的基本功能 using ;//提供画gdi+图像的高级功能 using system.drawing.drawing2d;//提供画高级二维,矢量图像功能 using system.drawing.imaging;//提供画gdi+图像的高级功能 namespace insight_cs.webcharts { public class piechart { public piechart() { } public void render(string title, string subtitle, int width, int height, dataset chartdata, stream target) { const int side_length = 400; const int pie_diameter = 200; datatable dt = chartdata.tables[0]; //通过输入参数,取得饼图中的总基数 float sumdata = 0; foreach(datarow dr ws) { sumdata += single(dr[1]); } //产生一个image对象,并由此产生一个graphics对象 bitmap bm = new bitmap(width,height); graphics g = graphics.fromimage(bm); //配置对象g的属性 g.scaletransform((single(width))/side_length,(single(height))/side_length); g.smoothingmode = smoothingmode.default; g.textrenderinghint = textrenderinghint.antialias; //画布和边的设定 g.clear(color.white); g.drawrectangle(pens.black,0,0,side_length-1,side_length-1); //画饼图标题 g.drawstring(title,new font("tahoma",24),brushes.black,new pointf(5,5)); //画饼图的图例 g.drawstring(subtitle,new font("tahoma",14),brushes.black,new pointf(7,35)); //画饼图 float curangle = 0; float totalangle = 0; for(int i=0;i&ws.count;i++) { curangle = ws[i][1]) / sumdata * 360; g.fillpie(new hartitemcolor(i)),100,65,pie_diameter,pie_diameter,totalangle,curangle); g.drawpie(pens.black,100,65,pie_diameter,pie_diameter,totalangle,curangle); totalangle += curangle; } //画图例框及其文字 g.drawrectangle(pens.black,200,300,199,99); g.drawstring("legend",new font("tahoma",12,fontstyle.bold),brushes.black,new pointf(200,300)); //画图例各项 pointf boxorigin = new pointf(210,330); pointf textorigin = new pointf(235,326); float percent = 0; for(int i=0;i&ws.count;i++) { g.fillrectangle(new hartitemcolor(i)),boxorigin.x,boxorigin.y,20,10); g.drawrectangle(pens.black,boxorigin.x,boxorigin.y,20,10); percent = ws[i][1]) / sumdata * 100; g.ws[i][0].tostring() + " - " + dt.rows[i][1].tostring() + " (" + string("0") + "%)",new font("tahoma",10),brushes.black,textorigin); boxorigin.y += 15; textorigin.y += 15; } //通过response.outputstream,将图像的内容发送到浏览器 bm.save(target, imageformat.gif); //回收资源 bm.dispose(); g.dispose(); } } //画条形图 public class barchart { public barchart() { } public void render(string title, string subtitle, int width, int height, dataset chartdata, stream target) { const int side_length = 400; const int chart_top = 75; const int chart_height = 200; const int chart_left = 50; const int chart_width = 300; datatable dt = chartdata.tables[0]; //计算最高的点 float highpoint = 0; foreach(datarow dr ws) { if(highpoint&single(dr[1])) { highpoint = single(dr[1]); } } //建立一个graphics对象实例 bitmap bm = new bitmap(width,height); graphics g = graphics.fromimage(bm); //配置条图图像和文字属性 g.scaletransform((single(width))/side_length,(single(height))/side_length); g.smoothingmode = smoothingmode.default; g.textrenderinghint = textrenderinghint.antialias; //设定画布和边 g.clear(color.white); g.drawrectangle(pens.black,0,0,side_length-1,side_length-1); //画大标题 g.drawstring(title,new font("tahoma",24),brushes.black,new pointf(5,5)); //画小标题 g.drawstring(subtitle,new font("tahoma",14),brushes.black,new pointf(7,35)); //画条形图 float barwidth = chart_width / (unt * 2); pointf barorigin = new pointf(chart_left + (barwidth / 2),0); float barheight = unt; for(int i=0;i&ws.count;i++) { barheight = ws[i][1]) * 200 / highpoint; barorigin.y = chart_top + chart_height - barheight; g.fillrectangle(new hartitemcolor(i)),barorigin.x,barorigin.y,barwidth,barheight); barorigin.x = barorigin.x + (barwidth * 2); } //配置边 g.drawline(new pen(color.black,2),new point(chart_left,chart_top),new point(chart_left,chart_top + chart_height)); g.drawline(new pen(color.black,2),new point(chart_left,chart_top + chart_height),new point(chart_left + chart_width,chart_top + chart_height)); //画图例框和文字 g.drawrectangle(new pen(color.black,1),200,300,199,99); g.drawstring("legend",new font("tahoma",12,fontstyle.bold),brushes.black,new pointf(200,300)); //画图例 pointf boxorigin = new pointf(210,330); pointf textorigin = new pointf(235,326); for(int i=0;i&ws.count;i++) { g.fillrectangle(new hartitemcolor(i)),boxorigin.x,boxorigin.y,20,10); g.drawrectangle(pens.black,boxorigin.x,boxorigin.y,20,10); g.ws[i][0].tostring() + " - " + dt.rows[i][1].tostring(),new font("tahoma",10),brushes.black,textorigin); boxorigin.y += 15; textorigin.y += 15; } //输出图像 bm.save(target, imageformat.gif); //资源回收 bm.dispose(); g.dispose(); } } public class chartutil { public chartutil() { } public static color getchartitemcolor(int itemindex) { color selectedcolor; switch(itemindex) { case 0: selectedcolor = color.blue; break; case 1: selectedcolor = d; break; case 2: selectedcolor = llow; break; case 3: selectedcolor = color.purple; break; default: selectedcolor = ; break; } return selectedcolor; } } } 代码分析: 1.引入一些namespace using system; using system.io;//用于文档存取 using system.data;//用于数据访问 using system.drawing;//提供画gdi+图像的基本功能 using ;//提供画gdi+图像的高级功能 using system.drawing.drawing2d;//提供画高级二维,矢量图像功能 using system.drawing.imaging;//提供画gdi+图像的高级功能 这些namespace将在后面被应用。 2.自定义一个namespace为insight_cs.webcharts,其中包括了两个类piechart和barchart,很清楚,class piechart是为画饼图而建,class barchart是为画条形图而建。由于class piechart和class barchar差不多,所以下面我们以饼图为例,进行代码分析。 3.类piechart建立一个方法render,此方法能够含一些参数。简单说明如下: 参数title,表示饼图上方的大标题文字。 参数subtitle,表示饼图上方的小标题文字。 参数width,height,表示了整个图像的大小。 参数chardata是个dataset对象实例,用于画图使用。 参数target是stream对象的实例,用于图像输出时使用。 4.为了增加可读性,定义一些常量: const int side_length = 400;//画布边长 const int pie_diameter = 200;//饼图直径 5.定义一个datatable,他是dataset中的一个数据表。其中存放了饼图的各个数据。 6.通过计算,得出饼图中的总基数sumdata。 7.建立了一个bitmap对象,他为要创建的图像提供了内存空间。并由此产生一个graphics对象,他封装了gdi+画图接口。transform和convert的区别 8.调用graphics对象的方法scaletransform(),他是用来设定图像比例的。 9.调用方法smoothingmode(),textrenderinghint()等来配置文字和图像的相关属性。 9.配置画布和边。 10.配置文字标题,图例,画饼图自身。 11.通过stream,将图像的内容发送到浏览器。 12.最后回收资源。 至此画饼图的类就完成了。画条形图的方法和画饼图的方法大同小异,这里就不展开讲了。 总体看来,构建画图的类没有我们想象的那样难,并没有多么高深的算法。其实整体思路,就似乎我们用笔在纸上画图是一摸相同的。关键是各个方法的使用和参数配置。 |
发表评论