最近有个项目,客户要求在客户端能动态显示不同年份数据,用折线图来表示,并且单击相关年份能查看详细数据,这里就有个问题放在面前,要从数据库里动态生成折线图,并且不只图,还能友好的操作。
分析了一下,可以通过至少三种技术做到,一是利用javascript脚本自身画图功能去实现,服务端的数据可以用Ajax来获取,这样就做到了客户端动态画折线图显示各年数据了,但这种方法要求的客户端的脚本代码相对复杂,实现起来有一定的困难。另一种方法是用插件技术实现,比如flashsilverlight,这种方法表现效果很好,问题是我不是专业的flashsilverlight手,实现有点难度。最后一种是靠自己的C#基本结合HTML来完成了。下面说说这种做法。
首先来构建客户端代码:
1<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MediaAdSystem.Index" %>
2
3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
5<html xmlns="http://www.w3.org/1999/xhtml" >
6<head runat="server">
7        <title>无标题页</title>
8</head>
9<body >
10
11<script language="javascript" type="text/javascript">
12// <!CDATA[
13//通过滚轮实现对图片的缩放
14function ChangImg(o)    
15{    
16var zoom=parseInt(o.style.zoom, 10)||100;
17zoom+=event.wheelDelta/12;
18if (zoom>0)
19 o.style.zoom=zoom+'%';    
20 //一个标签显示缩放百分比
21 document .getElementById ("bfb").innerHTML =Math.floor(zoom) +"%";
22return false;    
23}    
24// ]]>
25</script>
26        <form id="form1" runat="server">
27        <div>
28         </div>
29        <center >    
30                <table style="width: 100%;">
31                        <tr>
32                                <td>
33                                        第一年:<asp:TextBox ID="TextBox1" runat="server">90</asp:TextBox> 
34                                </td>
35                                <td>
36                                        第二年:<asp:TextBox ID="TextBox2" runat="server">46</asp:TextBox>  
37                                </td>
38                                <td>
39                                        第三年:<asp:TextBox ID="TextBox3" runat="server">23</asp:TextBox> 
40                                </td>
41                        </tr>
42                        <tr>
43                                <td>
44                                        第四年:<asp:TextBox ID="TextBox4" runat="server">123</asp:TextBox>  
45                                </td>
46                                <td>
47                                        第五年:<asp:TextBox ID="TextBox5" runat="server">56</asp:TextBox>  
48                                </td>
49                                <td>
50                                        第六年:<asp:TextBox ID="TextBox6" runat="server">333</asp:TextBox>  
51                                </td>
52                        </tr>
53                </table>        
54                    <span id="bfb">100%</span><asp:Button ID="Button6" runat="server" Text="生成图表" />        
55                <br />
56                <asp:ImageMap ID="ImageMap1" onmousewheel="return ChangImg(this)"    runat="server">
57                </asp:ImageMap>
58             </center>
59        </form>
60        </body>
61</html>
62
 
客户端主要是数据的录入,和Img图片标签的展示。我们发现,这里用的是ImageMap,并非普通的Image,这是因为我们要用到ImageMapMap的功能,通过点击相应年进入该年的详细信息页面。还有一点就是我们可以从JS的函数中能得到图片的缩放比例,显示在一个idbfbspan标签上。
下来我们就把客户端的数据,通过后台代码生成ImageMap:
1protected void Button1_Click(object sender, EventArgs e)
2                {
3                        int[] intarr = new int[6] { int.Parse(TextBox1.Text), int.Parse(TextBox2.Text), int.Parse(TextBox3.Text) ,
4                                                        int.Parse(TextBox4.Text), int.Parse(TextBox5.Text), int.Parse(TextBox6.Text)         };                        
5                        int step = 80;
6                        //画热点的图形
7                        for (int i = 0; i < 6; i++)
8                        {
9                                CircleHotSpot Circ = new CircleHotSpot();
10                                Circ.Radius = 5;
11                                Circ.X = i*step+10;
12                                Circ.Y = 340 - intarr[i];
13                                Circ.NavigateUrl = "http://www.baidu.com?year="+i;
14                                Circ.AlternateText = i.ToString ();
15                                Circ.Target = "_blank";
16                                ImageMap1.HotSpots.Add(Circ);
17                        }                
18                        ImageMap1.ImageUrl = "image1.aspx?c1=" + TextBox1.Text + "&c2=" + TextBox2.Text + "&c3=" + TextBox3.Text + "&c4=" + TextBox4.Text + "&c5=" + TextBox5.Text + "&c6=" + TextBox6.Text;            
19                }
20
 
代码中的for语句用来生成热点,热点的个数决定于数据。
接下来,我们看一下画图类,这个其在我利用Ajax无全页面提交实现动态画图 的文章中说过,这里只把代码共享出来。
1using System;
2using System.Collections;
3using System.Configuration;
4using System.Data;
5using System.Web;
6using System.Web.Security;
7using System.Web.UI;
8using System.Web.UI.HtmlControls;
9using System.Web.UI.WebControls;
10using System.Web.UI.WebControls.WebParts;
11using System.Drawing;
12using System.Drawing.Drawing2D;
13using System.Drawing.Imaging;
14
15public partial class image1 : System.Web.UI.Page
16{
17        protected void Page_Load(object sender, EventArgs e)
18        {
19                DrawMarket();
20        }
21        /**//// <summary>
22        /// 自动画折线图
23        /// </summary>
24        private void DrawMarket()
25        {
26                int[] ZbArr = new int[Request.QueryString.Count];
27                for (int i = 0; i < ZbArr.Length; i++)
28                {
29                        ZbArr[i] = int.Parse(Request.QueryString[i]);
30                }
31                int width = 600, height = 360;
32                Bitmap bm = new Bitmap(width, height);
33                Graphics g = Graphics.FromImage(bm);
34                g.Clear(Color.White);
35                Brush b = new SolidBrush(Color.Green);
36                Pen p = new Pen(Color.Black,1.8f);
37                Pen p1 = new Pen(Color.Green, 2);
38                p.EndCap = LineCap.ArrowAnchor ;
39                //画坐标系
40                g.DrawLine(p, 10, 340, 540, 340);
41                g.DrawLine(p, 10, 340, 10, 10);
42                g.DrawString("年", new Font("宋体", 15, FontStyle.Bold), b, 545, 332);
43                int step = 80;
44                //画折线
45                GraphicsPath graphPath = new GraphicsPath();
46                Point[] point = new Point[ZbArr.Length];
47                for (int i = 0; i < point.Length; i++)
48                {
49                        point[i].X = i * step + 10;
50                        point[i].Y = 340 - ZbArr[i];
51                }
52                Pen blackPen = new Pen(Color.Black, 3);
53                graphPath.AddLines(point);
54                g.DrawPath(p, graphPath);
55                //画点
56                for (int i = 0; i < point.Length; i++)
57                {
58                        g.DrawEllipse(p1, point[i].X - 5, point[i].Y - 5, 10, 10);
59                }                
60                bm.Save(this.Response.OutputStream, ImageFormat.Jpeg);
61                g.Dispose();
62                bm.Dispose();
63
64        }
65}
66
这种画图的效果相对来说明了,但出来的图的效果不是太好,需要进一步优化。