[Google Charts] Google Chart

  • 20731
  • 0

[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 圖片來呈現,要注意的是長條圖的第二欄之後(包含第二欄)其欄位格是必須相同

畫面

image

Line Chart

主要都跟 Column Chart 相同,要求也是第二欄之後的資料都必須相同格式,不同格式的話會出現此訊息

image

圖表資料的部分,這次轉為在 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;
        }
    }
}

畫面

image

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

畫面

image

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);
}

畫面

image

圖表切換

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;
        }
    }
}

畫面

image

最後說明一下 Google Chart 現在資料欄的格式只有 string、number、boolean、date、datetime 與 timeofday ,另外範例檔案下載中包含了北風資料庫。

範例檔案 下載

參考資料:

Google Developers

Google Code Playground

Google DataTable .Net Wrapper

DotBlogs 標籤: