[Google Charts] Google Chart
之前看了mis2000lab 的這篇文章,才知道 Google Chart 提供的圖表
愈來愈多,看完之後,就想來玩玩看,也順便把 Google Chart
的圖表使用方式記錄一下,詳細的資料,Google 官方文件有詳細介紹
使用 Google Chart 第一步,當然是讀取它的 API 了,Google Chart 需要三個類別庫
- The Google JSAPI API
- The Google Visualization library
- The library for the chart itself
在使用上來說,其實就引用 API 讀取哪一類別庫搞定了,來看程式碼吧
<script src="//www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
// The Google Visualization library && The library for the chart itself
google.load('visualization', '1.1', { 'packages': ['corechart'], 'language': 'zh' });
google.setOnLoadCallback(drawChart);
function drawChart()
{
// ... 繪製圖表
}
</script>
當然還有另一個做法,全部包到引用裡面
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1.1','packages':['corechart','motionchart']}]}"></script>
稍微說明一下,在
visualization 就是載入 Google Visualization library,然後 1.1 就是這類別庫的版本了,最後的 corechart 則是所要使用圖表類型類別庫,至於 language 只是語言的支援而已,這個不是圖表類別庫使用的必要條件(雖然感覺有無使用中文差距不大)。
接著圖表繪製的三種方式
- chart.draw()
- ChartWrapper
- DrawChart()
官方說明了這三個方式的優缺點與原理,此處就直接列範例
chart.draw()
google.setOnLoadCallback(drawChart);
function drawChart()
{
/// <summary>繪製圖表</summary>
var jsonData = $.ajax({
url: "../Handler/GetData.ashx",
dataType: "json",
async: false,
data: {cd:''}
}).responseText;
// Create the data table.
var data = new google.visualization.DataTable(jsonData);
// Set chart options
var options = {
title: 'chart.draw',
width: 900,
height: 400
}
var container = document.getElementById('chart_div');
var chart = new google.visualization.LineChart(container);
chart.draw(data, options);
}
ChartWrapper
google.setOnLoadCallback(drawChart);
function drawChart()
{
/// <summary>繪製圖表</summary>
var jsonData = $.ajax({
url: "../Handler/GetData.ashx",
dataType: "json",
async: false,
data: {ct:''}
}).responseText;
var wrapper = new google.visualization.ChartWrapper({
chartType: 'ColumnChart',
dataTable: jsonData,
options: { 'title': 'ChartWrapper',width:900,height:400 },
containerId: 'chart_div'
});
wrapper.draw();
}
DrawChart()
google.setOnLoadCallback(drawChart);
function drawChart()
{
/// <summary>繪製圖表</summary>
var jsonData = $.ajax({
url: "../Handler/GetData.ashx",
dataType: "json",
async: false,
data: {}
}).responseText;
google.visualization.drawChart({
chartType: 'ColumnChart',
dataTable: jsonData,
options: { 'title': 'ChartWrapper',width:900,height:400 },
containerId: 'chart_div'
});
}
接下來就列幾個圖表的程式範例
Column Chart
<head>
<script src="//code.jquery.com/jquery-1.10.1.min.js" type="text/javascript"></script>
<script src="//www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
google.load('visualization', '1.1', { 'packages': ['corechart'], 'language': 'zh' });
google.setOnLoadCallback(drawChart);
function drawChart()
{
/// <summary>繪製圖表</summary>
var jsonData = $.ajax({
url: "../Handler/GetData.ashx",
dataType: "json",
async: false,
data: {ct:"column"}
}).responseText;
// 建立資料表
// 方法一 json
var data = new google.visualization.DataTable(jsonData);
// 方法二 array 格式
//var data = google.visualization.arrayToDataTable(array);
// 設定圖表屬性
var options = {
title: '長條圖',
width: 900,
height: 400,
is3D: true, // 3D 效果
backgroundColor: '#daf3f3', // 背景顏色
vAxis: {
title: '縱軸標題',
titleTextStyle: { color: '#0b9727',fontSize:20,italic:false }
}, // 縱軸設定
hAxis: {
title: '橫軸標題',
titleTextStyle: { color: '#3e0fac', fontSize: 20, italic: false }
}, // 橫軸設定
axisTitlesPosition: "out" // 坐標軸標題位置 in:圖表內、out:圖表外、none:不顯示
}
// 只能使用 javascript 取得 container
var container = document.getElementById('chart_div');
var chart = new window.google.visualization.ColumnChart(container);
chart.draw(data, options);
// 轉換成 png 圖片
//chart_div.innerHTML = '<img src="' + chart.getImageURI() + '">';
}
</script>
<title>長條圖</title>
</head>
<body>
<h1>北風資料庫報表-長條圖</h1>
<hr />
<div id="chart_div">
</div>
</body>
</html>
在繪製圖表部分,主要可以分為兩個步驟,先是設定建立圖表的資料,然後是設定圖表屬性;建立圖表的資料中,將資料轉換進 google chart 資料表的方式有兩個,一個是 DataTable,一個是 arrayToDataTable 至於圖表屬性的設定,每個不同的圖表樣式都有幾個不同的圖表屬性與設定要求,這個部分可以參考官方文件,這邊附上範例 json 資料
"label" : "訂單編號",
"type" : "string"
},
{ "id" : "B",
"label" : "小計",
"type" : "number"
},
{ "id" : "C",
"label" : "對比列",
"type" : "number"
}
],
"rows" : [ { "c" : [ { "f" : null,
"v" : "1863.4000"
},
{ "f" : null,
"v" : "1863.4000"
},
{ "f" : null,
"v" : "1490.72001953125"
}
] },
{ "c" : [ { "f" : null,
"v" : "3597.9000"
},
{ "f" : null,
"v" : "3597.9000"
},
{ "f" : null,
"v" : "2878.319921875"
}
] },
{ "c" : [ { "f" : null,
"v" : "1552.6000"
},
{ "f" : null,
"v" : "1552.6000"
},
{ "f" : null,
"v" : "1242.07998046875"
}
] },
{ "c" : [ { "f" : null,
"v" : "654.0600"
},
{ "f" : null,
"v" : "654.0600"
},
{ "f" : null,
"v" : "523.247998046875"
}
] },
{ "c" : [ { "f" : null,
"v" : "2490.5000"
},
{ "f" : null,
"v" : "2490.5000"
},
{ "f" : null,
"v" : "1992.4"
}
] }
]
}
說明的部分,就在註解上了
using System;
using System.Web;
using System.Data;
using System.Collections.Generic;
using Newtonsoft.Json; // 使用 Json.Net
public class GetData : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/json";
string sql = "SELECT convert(VARCHAR(10), ShippedDate, 120) AS ShippedDate,OrderID,Subtotal FROM [Summary of Sales by Quarter] WHERE ShippedDate BETWEEN '1996-07-10' AND '1996-07-15' ORDER by ShippedDate,OrderID";
// 圖表類型
string ct = context.Request["ct"] ?? string.Empty;
using (DataTable dt = new DataToolkit().GetDatatable(sql))
{
string str_json = dataTableToJson(dt);
context.Response.Write(str_json);
}
}
/// <summary>
/// 轉換格式
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
public string dataTableToJson(DataTable dt)
{
// Column Chart 與 Line Chart
// 第一欄位為名稱欄位
// 二、三欄...至 n 欄其資料格式必須相同
RootObject graph = new RootObject
{
cols = new List<ColInfo>
{
// id 可直接填空字串,預設會自動建立
// label 為提示訊息前置值,假如 沒有設定 f 資料,預設會讀取 label 加上此資料格的值 例如:小計:654.0600
// type 此欄資料格式,只有 boolean、number、string、date、datetime、timeofday 六種格式
new ColInfo { id = "A", label = "訂單編號", type = "string" },
new ColInfo { id = "B", label = "小計", type = "number" },
new ColInfo { id = "C", label = "對比列", type = "number" },
},
rows = new List<DataPointSet>()
};
List<DataPointSet> rows = new List<DataPointSet>();
foreach (DataRow dr in dt.Rows)
{
DataPointSet cSetRow = new DataPointSet();
List<DataPoint> cSetList = new List<DataPoint>();
DataPoint cSetProp = new DataPoint();
cSetProp.v = dr["OrderID"].ToString();
cSetList.Add(cSetProp);
cSetProp.v = dr["Subtotal"].ToString();
cSetList.Add(cSetProp);
cSetProp = new DataPoint();
cSetProp.v = (float.Parse(dr["Subtotal"].ToString()) * 0.8).ToString();
cSetList.Add(cSetProp);
cSetRow.c = cSetList;
rows.Add(cSetRow);
}
graph.rows = rows;
return JsonConvert.SerializeObject(graph);
}
public class ColInfo
{
public string id { get; set; }
public string label { get; set; }
public string type { get; set; }
}
public class DataPoint
{
public string v { get; set; } // 圖表中 欄位數值
public string f { get; set; } // 圖表中 欄位提示訊息
}
public class DataPointSet
{
public List<DataPoint> c { get; set; }
}
public class RootObject
{
public List<ColInfo> cols { get; set; }
public List<DataPointSet> rows { get; set; }
//public Dictionary<string, string> p { get; set; }
}
public bool IsReusable
{
get
{
return false;
}
}
}
var container = document.getElementById('chart_div');
var chart = new window.google.visualization.ColumnChart(container);
取得 container 部分是要求 DOM element,不要用 JQuery 去取得 element。設定觸發事件部分就延用官方的範例,然後現在還可以將繪製的圖表轉換成 png 圖片來呈現,要注意的是長條圖的第二欄之後(包含第二欄)其欄位格是必須相同
畫面
Line Chart
主要都跟 Column Chart 相同,要求也是第二欄之後的資料都必須相同格式,不同格式的話會出現此訊息
圖表資料的部分,這次轉為在 Client 端設定欄位,然後轉換一下格式
google.setOnLoadCallback(drawChart);
function drawChart()
{
/// <summary>繪製圖表</summary>
// Create the data table.
var data = new google.visualization.DataTable();
//設定資料欄 (資料型態, 欄位名稱)
data.addColumn('date', '日期');
data.addColumn('number', '小計');
data.addColumn('number', '對比列');
$.ajax({
url: "../Handler/GetData.ashx",
dataType: "json",
async: false,
data: { ct: "line" },
success:
function (jsondata)
{
$.map(jsondata, function (key, val)
{
// 加入原始資料
data.addRow([
{
v:new Date(key.ShippedDate),
f: 'Date:' + key.ShippedDate
},
key.Subtotal,
key.Subtotal * 0.8
]);
});
}
});
var options = {
title: '折線圖',
width: 900,
height: 400,
pointSize:5 // 標記大小
}
// 取得 container DOM element
var container = document.getElementById('chart_div');
var chart = new window.google.visualization.LineChart(container);
chart.draw(data, options);
}
using System;
using System.Web;
using System.Data;
using System.Collections.Generic;
using Newtonsoft.Json; // 使用 Json.Net
public class GetData : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/json";
string sql = "SELECT convert(VARCHAR(10), ShippedDate, 120) AS ShippedDate,OrderID,Subtotal FROM [Summary of Sales by Quarter] WHERE ShippedDate BETWEEN '1996-07-10' AND '1996-07-15' ORDER by ShippedDate,OrderID";
// 圖表類型
string ct = context.Request["ct"] ?? string.Empty;
using (DataTable dt = new DataToolkit().GetDatatable(sql))
{
string str_json = JsonConvert.SerializeObject(dt, Formatting.Indented);
context.Response.Write(str_json);
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
畫面
Pie Chart
google.setOnLoadCallback(drawChart);
function drawChart(Charttype)
{
/// <summary>繪製圖表</summary>
// Create the data table.
var data = new google.visualization.DataTable();
//設定資料欄 (資料型態, 欄位名稱)
data.addColumn('string', 'id');
data.addColumn('number', '小計');
var jsonData = $.ajax({
url: "../Handler/GetData.ashx",
dataType: "json",
async: false,
data: { ct: "pie" },
success:
function (jsondata)
{
$.map(jsondata, function (key, val)
{
// 加入原始資料
data.addRow([
key.OrderID.toString(),
key.Subtotal
]);
});
}
});
// Set chart options
var options = {
title: "圓餅圖",
width: 900,
height: 400,
//pieSliceText: 'label', // 圓餅區塊上顯示 label 資料,預設顯示百分比
is3D: true
}
var chart = new window.google.visualization.PieChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
Server 端的資料讀取跟 Line Chart 一樣,唯一需要注意的是 Pie Chart 第一欄的格式必須為 string
畫面
Motion Chart
Motion Chart 前兩欄限定格式 第一欄為 string ,第二欄為 date,泛行處理常式的 code 跟 Line Chart 相同
google.setOnLoadCallback(drawChart);
function drawChart()
{
/// <summary>繪製圖表</summary>
// Create the data table.
var data = new google.visualization.DataTable();
//設定資料欄 (資料型態, 欄位名稱)
// Motion Chart 前兩欄限定格式 第一欄為 string ,第二欄為 date
data.addColumn('string', '編號');
data.addColumn('date', '日期');
data.addColumn('number', '小計');
$.ajax({
url: "../Handler/GetData.ashx",
dataType: "json",
async: false,
data: { ct: "motion" },
success:
function (jsondata)
{
$.map(jsondata, function (key, val)
{
// 加入原始資料
data.addRow([key.OrderID.toString(), new Date(key.ShippedDate), key.Subtotal]);
});
}
});
// Set chart options
var options = {
title: "動態圖",
width: 900,
height: 400
}
var chart = new window.google.visualization.MotionChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
畫面
圖表切換
packages 中必須把使用的圖表類別庫載入
<head>
<script src="//code.jquery.com/jquery-1.10.1.min.js" type="text/javascript"></script>
<script src="//ajax.aspnetcdn.com/ajax/jquery.ui/1.10.4/jquery-ui.min.js" type="text/javascript"></script>
<link href="//ajax.aspnetcdn.com/ajax/jquery.ui/1.10.4/themes/redmond/jquery-ui.css" rel="stylesheet" type="text/css" />
<script src="//www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
google.load('visualization', '1.1', { 'packages': ['motionchart','corechart'], 'language': 'zh' });
google.setOnLoadCallback(initCharts);
function initCharts()
{
/// <summary>
/// 初始化圖表,呼叫 function drawChart
///</summary>
drawChart($(":radio[name='ChartType']:checked").val());
}
function selectChart(CharttypeId)
{
/// <summary>按照圖表類型代號,傳回圖表類型</summary>
/// <param name="CharttypeId" type="String">圖表類型代號</param>
/// <returns type="String" />
var ChartType = "";
switch (CharttypeId)
{
case "column":
ChartType = "ColumnChart";
break;
case "line":
ChartType = "LineChart";
break;
case "pie":
ChartType = "PieChart";
break;
case "motion":
ChartType = "MotionChart";
break;
}
return ChartType;
}
function drawChart(CharttypeId)
{
/// <summary>繪製圖表</summary>
/// <param name="CharttypeId" type="String">圖表類型代號</param>
var jsonData = $.ajax({
url: "../Handler/GetData.ashx",
dataType: "json",
async: false,
data: { ct: '' }
}).responseText;
// Create the data table.
var data = new google.visualization.DataTable(jsonData);
var ChartType = selectChart(CharttypeId);
// Set chart options
// 各種屬性都可以到此查詢,https://developers.google.com/chart/interactive/docs/gallery
var options = {
title: ChartType,
width: 900,
height: 400
}
// 取得 container DOM element
var container = document.getElementById('chart_div');
var chart = new window['google']['visualization'][ChartType](container);
chart.draw(data, options);
}
$(function ()
{
//#region Search Button bind click event.
$('#btnShowChart').on('click', function ()
{
drawChart($(":radio[name='ChartType']:checked").val());
});
//#endregion
});
</script>
<title>圖表類型切換</title>
</head>
<body>
<h1>北風資料庫報表</h1>
<div>
<p>
<span>報表類型:</span>
<input id="rdCTColumn" checked="checked" name="ChartType" type="radio" value="column" />
<span>長條圖</span>
<input id="rdCTLine" name="ChartType" type="radio" value="line" />
<span>折線圖</span>
<input id="rdCTPie" name="ChartType" type="radio" value="pie" />
<span>圓餅圖</span>
<input id="rdCTMotion" name="ChartType" type="radio" value="motion" />
<span>動態圖</span>
</p>
<p>
<input id="btnShowChart" type="button" value="查詢" />
</p>
</div>
<hr />
<div id="chart_div">
</div>
</body>
</html>
然後這次使用 Google DataTable .Net Wrapper 這個來轉換 DataTable,可以透過 NuGet 取得,或是其介紹頁下載
PM> Install-Package Google.DataTable.Net.Wrapper
using System;
using System.Web;
using System.Data;
using System.Collections.Generic;
using Newtonsoft.Json;
using GDNW = Google.DataTable.Net.Wrapper;
public class GetData : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "application/json";
string sql = "SELECT convert(VARCHAR(10), ShippedDate, 120) AS ShippedDate,OrderID,Subtotal FROM [Summary of Sales by Quarter] WHERE ShippedDate BETWEEN '1996-07-10' AND '1996-07-15' ORDER by ShippedDate,OrderID";
using (DataTable dt = new DataToolkit().GetDatatable(sql))
{
GDNW.DataTable tt = GDNW.SystemDataTableConverter.Convert(dt);
string str_json = tt.GetJson();
context.Response.Write(str_json);
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
畫面
最後說明一下 Google Chart 現在資料欄的格式只有 string、number、boolean、date、datetime 與 timeofday ,另外範例檔案下載中包含了北風資料庫。
範例檔案 下載