天天看點

Google圖表建立類 —— 高度封裝!強力圖表解決方案!

更為可貴的是,圖表圖形的計算和渲染完全由Google伺服器處理,生成的圖檔也從Google伺服器下載下傳,你的伺服器就可以大幅節約運算及網絡流量資源。

故此,将Google圖表API作為網站的圖表解決方案,是一個絕佳的選擇。

這是Google官方提供的一個範例:

它的Url為:

<code>http://chart.apis.google.com/chart?cht=p3&amp;chd=t:60,40&amp;chs=250x100&amp;chl=Hello|World</code>

你可以嘗試修改Url中的各個參數,圖表對應的圖像就會發生變化。

這些參數在Google官方說明文檔中都有詳盡的說明,但即便如此,它們看起來也還是像天書一般,并且非常雜亂。

上面那個還僅僅是一個簡單之至的圖表,來看看文章末尾提供的範例所對應的Url:

http://chart.apis.google.com/chart?cht=lc&amp;chs=1000x300&amp;chtt=30天内日志記錄量統計圖&amp;chco=BD6CE9FF,1865BBFF,0AA413FF,FF9E1FFF,FF565EFF&amp;chm=B,BD6CE932,0,0,0|B,1865BB32,1,0,0|B,0AA41332,2,0,0|B,FF9E1F32,3,0,0|B,FF565E32,4,0,0&amp;chdl=管理者|異常|系統|使用者&amp;chdlp=b&amp;chd=t:0,12,0,180,103,0,71,0,0,2,0,0,0,0,0,47,0,0,0,127,0,11,0,0,0,0,0,0,0,118,41|0,0,111,22,2,0,3,0,27,2,23,19,9,18,30,18,0,6,16,3,0,8,0,0,4,0,1,0,0,21,3|0,4,77,80,26,0,7,0,50,18,49,42,33,74,77,56,0,32,83,38,0,18,0,0,46,8,24,0,4,97,48|0,1,4,9,1,0,3,0,4,1,1,4,2,3,12,9,0,7,7,2,0,1,0,0,5,8,23,0,1,3,2&amp;chds=0,180&amp;chxt=x,r,y&amp;chxr=1,0,180|2,0,180&amp;chxp=1,22.9677419354839,11.1612903225806,31.9677419354839,3.64516129032258&amp;chxl=0:|6.14|6.15|6.16|6.17|6.18|6.19|6.20|6.21|6.22|6.23|6.24|6.25|6.26|6.27|6.28|6.29|6.30|7.1|7.2|7.3|7.4|7.5|7.6|7.7|7.8|7.9|7.10|7.11|7.12|7.13|7.14|1:|管理者均值|異常均值|系統均值|使用者均值&amp;chf=bg,s,FAFAFAFF|c,lg,90,EDFDFDFF,0,EDFDFD00,1

啊哈,是不是已經噴血了?

顯然這樣的圖表不适合人工建立,而即使通過程式來建立,也非常麻煩:資料統計的邏輯本來就有夠複雜了,再加上頻繁地檢視文檔、測試……

有什麼辦法能讓圖表的建立變得輕松、簡單嗎?

為實作這一目标,我決定将圖表的建立操作封裝起來,有了封裝後的類庫,就可以這樣輕松的建立一個圖表Url:

建立一個圖表對象 &gt; 為之添加各種所需參數 &gt; 生成代碼

以上面那個Google的三維餅圖範例為例,我們通過下面的代碼生成一個同樣的圖表:

[TestMethod()]

public void 生成代碼Test2()

{

    var 圖表 = new 三維餅圖();

    圖表.添加參數(new 圖表尺寸 { 高度 = 100, 寬度 = 250 });

    var label = new 餅圖和指數标簽();

    label.标簽清單.Add("Hello");

    label.标簽清單.Add("World");

    圖表.添加參數(label);

    var data = new 文本編碼資料();

    data.資料清單.Add(new System.Collections.Generic.List&lt;double&gt;());

    data.資料清單[0].Add(60);

    data.資料清單[0].Add(40);

    圖表.添加參數(data);

    var expected = "http://chart.apis.google.com/chart?cht=p3&amp;chs=250x100&amp;chl=Hello|World&amp;chd=t:60,40";

    var actual = 圖表.生成代碼();

    Assert.AreEqual(expected, actual);

}

感覺如何?這樣基本上就把整個建立流程語義化了,建立圖表的時候再也不用頻繁檢視文檔了吧!

此類庫使用中文是出于三個原因:

其一就是我個人的寫程式習慣,我覺得中文最便于自己了解,中文和英文放在一起非常顯眼,并且中文在VisualStudio的智能感覺清單中始終處于最下方,這樣自定義的東西一下就能找到;

其二就是中文畢竟是我們的母語,大多數人一眼就能了解,省去翻譯的麻煩;

其三就是其中的大部分命名直接引用或參考了Google的中文文檔中的命名,這樣大家在使用時能夠更友善地對照文檔。

此類庫中有兩大基類:參數、圖表

圖表類就是各種類型的圖表的基類,如餅圖、三維餅圖、折線圖、條形圖等。

參數即為圖表的參數,如尺寸、資料、顔色、标簽、标題等均繼承于此類。

因為各種圖表所能夠支援的參數類型不盡相同,是以除了參數本身的封裝類型之外,還定義了參數的支援接口,圖表隻有繼承了這些支援接口,才能通過擴充方法“添加參數()”添加相應類型的參數:

擴充方法定義:

上圖中的“唯一參數辨別”屬性是用于避免參數重複添加的屬性。

此外,參數還定義了一種依賴機制:

在生成代碼時,如果僅有此參數,而沒有其所需的某種依賴參數,則報告異常。

如:圖表圖例參數需依賴于圖表顔色參數

功能點:餅圖 四色 标簽 标題 條紋背景 整體不透明度控制

功能點:折線圖 三色 圖例 漸變背景 标題 軸标簽定制

功能點:條形圖 三色 縱向分布 圖例 漸變背景 标題 軸标簽定制

在頁面中添加一個Image控件,然後在Page_Load中書寫代碼實作日志資訊統計:

protected void Page_Load(object sender, EventArgs e)

    if (!IsPostBack)

    {

        var 圖表 = new 折線圖();

        圖表.類型 = 折線圖類型.均布折線圖;

        圖表.添加參數(new 圖表尺寸 { 寬度 = 1000, 高度 = 300 });

        圖表.添加參數(new 圖表标題 { 标題 = "30天内日志記錄量統計圖" });

        圖表.添加參數(new 實體填充 { 填充類型 = 實體填充類型.整體背景填充, 顔色 = Color.FromArgb(250, 250, 250) });

        var xt = new 線性漸變填充();

        圖表.添加參數(xt);

        xt.角度 = 90;

        xt.填充類型 = 線性漸變填充類型.圖表區域背景填充;

        xt.色标清單.Add(new 色标 { 位置 = 0, 顔色 = Color.FromArgb(237, 253, 253) });

        xt.色标清單.Add(new 色标 { 位置 = 1, 顔色 = Color.FromArgb(0, 237, 253, 253) });

        var color = new 圖表顔色();

        圖表.添加參數(color);

        color.顔色清單.AddRange(new Color[] { Color.FromArgb(189, 108, 233), Color.FromArgb(24, 101, 187), Color.FromArgb(10, 164,19), Color.FromArgb(255, 158, 31), Color.FromArgb(255, 86, 94), });

        var colorfill = new 區域填充();

        圖表.添加參數(colorfill);

        colorfill.填充清單.Add(new 資料實體填充 { 顔色 = Color.FromArgb(50, 189, 108, 233), 目标資料組索引 = 0 });

        colorfill.填充清單.Add(new 資料實體填充 { 顔色 = Color.FromArgb(50, 24, 101, 187), 目标資料組索引 = 1 });

        colorfill.填充清單.Add(new 資料實體填充 { 顔色 = Color.FromArgb(50, 10, 164, 19), 目标資料組索引 = 2 });

        colorfill.填充清單.Add(new 資料實體填充 { 顔色 = Color.FromArgb(50, 255, 158, 31), 目标資料組索引 = 3 });

        colorfill.填充清單.Add(new 資料實體填充 { 顔色 = Color.FromArgb(50, 255, 86, 94), 目标資料組索引 = 4 });

        var tl = new 圖表圖例();

        圖表.添加參數(tl);

        tl.位置 = 圖表圖例位置.下;

        var td = new 帶有資料換算的文本編碼資料();

        圖表.添加參數(td);

        td.換算标準.Add(new 範圍限定());

        td.換算标準[0].最大值 = double.MinValue;

        td.換算标準[0].最小值 = double.MaxValue;

        var mtg = new 多軸标簽();

        圖表.添加參數(mtg);

        var dz = new 軸标簽 { 類型 = 軸類型.底部 };

        var a = new 軸标簽 { 類型 = 軸類型.右側 };

        mtg.軸标簽清單.Add(dz);

        mtg.軸标簽清單.Add(a);

        using (var c = new DatabaseEntities())

        {

            var d = DateTime.Now.AddDays(-30);

            var s = c.日志.Select(f =&gt; new { f.觸發時間, f.所屬日志類型.名稱 }).Where(f =&gt; f.觸發時間 &gt;= d).ToList().GroupBy(f =&gt;f.名稱);

            bool first = true;

            foreach (var f in s)

            {

                tl.圖例名稱清單.Add(f.Key);

                var dl = new List&lt;double&gt;();

                for (int i = -30; i &lt;= 0; i++)

                {

                    var od = DateTime.Today.AddDays(i);

                    if (first)

                    {

                        dz.軸标簽清單.Add(od.Month + "." + od.Day);

                    }

                    var cd = f.Count(v =&gt; v.觸發時間.Date == od);

                    dl.Add(cd);

                    td.換算标準[0].最大值 = Math.Max(td.換算标準[0].最大值, cd);

                    td.換算标準[0].最小值 = Math.Min(td.換算标準[0].最小值, cd);

                }

                a.軸标簽清單.Add(f.Key + "均值");

                a.軸标簽位置清單.Add(dl.Average());

                td.資料清單.Add(dl);

                first = false;

            }

        }

        mtg.軸标簽清單.Add(new 軸标簽 { 類型 = 軸類型.左側, 軸範圍 = new 軸範圍 { 起始值 = (int)td.換算标準[0].最小值, 終止值 =(int)td.換算标準[0].最大值 } });

        a.軸範圍 = new 軸範圍 { 起始值 = (int)td.換算标準[0].最小值, 終止值 = (int)td.換算标準[0].最大值 };

        Image1.ImageUrl = 圖表.生成代碼();

    }

生成的圖表:

目前還沒有将所有圖表及參數全部封裝,但現有的功能已足以應付多數正常應用。

<a href="http://cid-0612298d2255e149.skydrive.live.com/self.aspx/.Public/%E6%96%87%E6%A1%A3/Google%E5%9B%BE%E8%A1%A8%E7%B1%BB%E5%9B%BE.png" target="_blank">檢視目前封裝好的類示意圖</a>

另外,我也将提供類庫的源代碼,供大家自行擴充需要的功能:

下載下傳類庫源代碼:

<a href="http://cid-0612298d2255e149.skydrive.live.com/self.aspx/.Public/%E6%96%87%E6%A1%A3/Google%E5%9B%BE%E8%A1%A820090715010729.rar?sa=625317065" target="_blank"></a>

我的設計還很不成熟,是以難免在此類庫中存有一些設計缺陷,極力歡迎各位朋友指導、指正。

還有什麼需求或想法,也歡迎在此留言述說。

本文轉自斯克迪亞部落格園部落格,原文連結:http://www.cnblogs.com/SkyD/archive/2009/07/15/1523759.html,如需轉載請自行聯系原作者

繼續閱讀