更為可貴的是,圖表圖形的計算和渲染完全由Google伺服器處理,生成的圖檔也從Google伺服器下載下傳,你的伺服器就可以大幅節約運算及網絡流量資源。
故此,将Google圖表API作為網站的圖表解決方案,是一個絕佳的選擇。
這是Google官方提供的一個範例:
它的Url為:
<code>http://chart.apis.google.com/chart?cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World</code>
你可以嘗試修改Url中的各個參數,圖表對應的圖像就會發生變化。
這些參數在Google官方說明文檔中都有詳盡的說明,但即便如此,它們看起來也還是像天書一般,并且非常雜亂。
上面那個還僅僅是一個簡單之至的圖表,來看看文章末尾提供的範例所對應的Url:
http://chart.apis.google.com/chart?cht=lc&chs=1000x300&chtt=30天内日志記錄量統計圖&chco=BD6CE9FF,1865BBFF,0AA413FF,FF9E1FFF,FF565EFF&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&chdl=管理者|異常|系統|使用者&chdlp=b&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&chds=0,180&chxt=x,r,y&chxr=1,0,180|2,0,180&chxp=1,22.9677419354839,11.1612903225806,31.9677419354839,3.64516129032258&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:|管理者均值|異常均值|系統均值|使用者均值&chf=bg,s,FAFAFAFF|c,lg,90,EDFDFDFF,0,EDFDFD00,1
啊哈,是不是已經噴血了?
顯然這樣的圖表不适合人工建立,而即使通過程式來建立,也非常麻煩:資料統計的邏輯本來就有夠複雜了,再加上頻繁地檢視文檔、測試……
有什麼辦法能讓圖表的建立變得輕松、簡單嗎?
為實作這一目标,我決定将圖表的建立操作封裝起來,有了封裝後的類庫,就可以這樣輕松的建立一個圖表Url:
建立一個圖表對象 > 為之添加各種所需參數 > 生成代碼
以上面那個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<double>());
data.資料清單[0].Add(60);
data.資料清單[0].Add(40);
圖表.添加參數(data);
var expected = "http://chart.apis.google.com/chart?cht=p3&chs=250x100&chl=Hello|World&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 => new { f.觸發時間, f.所屬日志類型.名稱 }).Where(f => f.觸發時間 >= d).ToList().GroupBy(f =>f.名稱);
bool first = true;
foreach (var f in s)
{
tl.圖例名稱清單.Add(f.Key);
var dl = new List<double>();
for (int i = -30; i <= 0; i++)
{
var od = DateTime.Today.AddDays(i);
if (first)
{
dz.軸标簽清單.Add(od.Month + "." + od.Day);
}
var cd = f.Count(v => 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,如需轉載請自行聯系原作者