2020年9月13日 星期日

以 jQuery 為基礎的繪圖函式庫 jqPlot

最近在一本舊書上看到 jqPlot 這個以 jQuery 為基礎建構的繪圖函式庫 :

# Beginning JavaScript Charts-With jqPlot, d3, and Highcharts (Apress, 2013)


Source : Apress


利用此函式庫可以在網頁上輕鬆地繪製折線圖, 分布圖, 圓餅圖等等資料分析常見的統計圖形, 但很可惜因為缺乏開發人員繼續投入, 此開源專案已於 2018-09-30 終止開發而封存了, 參考 :

https://groups.google.com/g/jqplot-dev/c/tDkY2z0q2t4

原開發者建議使用者可改用 Chart.js 專案.

jqPlot 首頁與 GitHub 寄存庫如下 :

http://www.jqplot.com/
https://github.com/jqPlot/jqPlot/

下載 jqPlot (最新也是最後版本 1.0.9) :

http://www.jqplot.com/download/

教學文件參考 :

https://www.jsdelivr.com/package/npm/jqplot

中文教學文件參考 :

jqPlot圖表外掛使用說明(一)
[JQUERY]輕鬆使用jquery開發的統計圖表UI---JQPLOT

雖然 jqPlot 很舊了而且已停止開發, 但基於想跟其他繪圖函式庫做個比較, 所以花了點時間緬懷一下這個函式庫, 當初開發者應該花了不少心力.

使用 jqPlot 的方法很簡單, 下載的 zip 解開後, 複製其中的 jquery.jqplot.min.css 與 jquery.jqplot.min.js 這兩個檔案到專案資料夾下即可, 例如 :

<script src="jquery/jquery.min.js"></script>
<script src="jquery/jquery.jqplot.min.js"></script>
<link href="jquery/jquery.jqplot.min.css" rel="stylesheet">

也可以使用 CDN 資源, 參考 :

https://cdnjs.com/libraries/jqPlot
https://www.jsdelivr.com/package/npm/jqplot

例如 :

<script src="jquery/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.css" rel="stylesheet">

注意, jqPlot 是以 jQuery 為基礎而開發的函式庫, 因此務必先匯入 jQuery 函式庫. 事實上這三個檔案只是 jqPlot 繪圖功能的基本款而已, 較複雜之設定與功能必須另外添加外掛 (plug-in).

jqPlot 的繪圖容器是一個 div 元素, 可用 style 設定容器的大小 :

<div id="chart" style="width:400px; height:300px;"></div>

然後呼叫 $.jqplot("chart", data) 方法傳入容器 id 與繪圖資料 data 即可 :

$.jqplot('chart', data [, options]);

其中第三參數為用來設定繪圖參數的選項物件, 若未指定則以 jqPlot 預設值設定. 其次 data 是資料陣列, 可以是二維 (只有 Y 軸資料) 或三維陣列 (提供 X,Y 軸座標對資料), 這樣可以同時繪製多組圖形, 例如 :

var data=[[100, 100, 75, 99, 89, 100, 85, 95, 77]];

我參考教學文件做了一些簡單的測試 :


測試 1 : jqPlot 繪製單組資料折線圖 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta http-equiv="cache-control" content="no-cache">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.css" rel="stylesheet">
    <style>
    </style>
  </head>
  <body>
    <div id="chart" style="width:400px; height:300px;"></div>
    <script>
      $(function(){
        var data=[[100, 100, 75, 99, 89, 100, 85, 95, 77]];
        $.jqplot('chart', data);
        });
    </script>
  </body>
</html>

此例中二維陣列 data 中只有一個元素, 表示只有一組 Y 軸資料, jqPlot 預設會以折線圖繪製圖形, 結果如下 :




可見沒有提供 X 軸資料時預設是以 1 起始之序數 1, 2, 3, 4, ... 為 X 軸座標, 且 X 軸會前後多 1 個單位. 設定繪圖容器 style 屬性中的 width 與 height 就可以控制圖形的大小.

下面是同時繪製多組資料的範例 :


測試 2 : jqPlot 繪製多組資料折線圖 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta http-equiv="cache-control" content="no-cache">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.css" rel="stylesheet">
    <style>
    </style>
  </head>
  <body>
    <div id="chart" style="width:400px; height:300px;"></div>
    <script>
      $(function(){
        var data=[[100, 100, 75, 99, 89, 100, 85, 95, 77],
                  [78, 55, 66, 60, 80, 75, 80, 83, 71],
                  [45, 49, 53, 56, 72, 50, 75, 78, 67]];
        $.jqplot('chart', data);
        });
    </script>
  </body>
</html>

此例所傳入之 data 變數為具有多組資料之二維陣列, 結果如下 :




可見當有多組資料時, jqPlot 會自動以不同顏色繪製圖形.

上面兩個例子都只有提供 Y 軸資料, 如果以 [X, Y] 座標對表示的話, 資料就要用三維陣列表示, 範例 1 的 data 應是這樣 :

var data=[[[1, 100], [2, 100], [3, 75], [4, 99], [5, 89], [6, 100], [7, 85], [8, 95], [9, 77]]];

而範例 2 則是如下 :

var data=[[[1, 100], [2, 100], [3, 75], [4, 99], [5, 89], [6, 100], [7, 85], [8, 95], [9, 77]],
                [[1, 78], [2, 55], [3, 66], [4, 60], [5, 80], [6, 75], [7, 80], [8, 83], [9, 71],
                [[1, 45], [2, 49], [3, 53], [4, 56], [5, 729], [6, 50], [7,75], [8, 78], [9, 67]];

實務上同時提供 [X, Y] 座標的場合較常見, 因為 X 軸是 1, 2, ,3, 4 ... 這種畢竟是少數. 注意, [X, Y] 座標軸對不一定要照 X 大小排序, jqPlot 讀取後會自動排序, 當然以資料可讀性來說還是依照 X 由小到大排序為宜.

上面兩個範例所繪製的圖形都沒有傳入第三參數選項物件 options, 這時 jqPlot 就以預設設定繪圖, 預設並無圖形標題 (title) 與軸標籤 (Axes labels), 如果要加上這些東西必須傳入帶有 title 與 axes 屬性之選項物件, 其中 axes 值為一個子物件, 可用 xaxis 與 yaxis 分別設定其標籤 lable 等屬性, 例如 :


測試 3 : 傳入選項物件 options 設定標題與 X, Y 軸標籤 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta http-equiv="cache-control" content="no-cache">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.css" rel="stylesheet">
    <style>
    </style>
  </head>
  <body>
    <div id="chart" style="width:400px; height:300px;"></div>
    <script>
      $(function(){
        var data=[[100, 100, 75, 99, 89, 100, 85, 95, 77],
                  [78, 55, 66, 60, 80, 75, 80, 83, 71],
                  [45, 49, 53, 56, 72, 50, 75, 78, 67]];
        var options={title: "月收盤價",
                     axes: {xaxis: {label: "月份"},
                            yaxis: {label: "價格"}
                            }
                     };
                     };
        $.jqplot('chart', data, options);
        });
    </script>
  </body>
</html>

結果如下 : 


可見圖形標題與 X, Y 軸標籤這下都有了.

坐標軸物件 axes 的子物件中, 除了 label 屬性外還有許多其他屬性可用來控制座標軸的顯示, 例如 pad 屬性是用來設定資料邊界與座標軸上下限之間的空隙, 預設會坐標軸上下限會比資料邊界多一個單位, 例如上面範例中 X 軸資料邊界為 1~9, 但預設 X 座標是 0~10, 而 Y 軸也是多出一格空隙, 如果不想要這個空隙, 可將 pad 屬性設為 0 或 1, 例如 :


測試 4 : 用 pad 屬性去除資料邊界與座標軸上下限之間的空隙 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta http-equiv="cache-control" content="no-cache">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.css" rel="stylesheet">
    <style>
    </style>
  </head>
  <body>
    <div id="chart" style="width:400px; height:300px;"></div>
    <script>
      $(function(){
        var data=[[100, 100, 75, 99, 89, 100, 85, 95, 77],
                  [78, 55, 66, 60, 80, 75, 80, 83, 71],
                  [45, 49, 53, 56, 72, 50, 75, 78, 67]];
        var options={title: "月收盤價",
                     axes: {xaxis: {label: "月份",
                                    pad: 0 
                                    },
                            yaxis: {label: "價格",
                                    pad: 0 
                                    }
                            }
                     };
        $.jqplot('chart', data, options);
        });
    </script>
  </body>
</html>

結果如下 :




可見現在資料與 X 坐標軸起訖都是 1~9, 而 Y 軸也去掉一格空隙了.

如果 pad 設為 2 的話, 表示空隙會變 2 倍, 例如 :


測試 5 : 將 pad 屬性設為 2 的效果 (空隙增兩倍) [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta http-equiv="cache-control" content="no-cache">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.css" rel="stylesheet">
    <style>
    </style>
  </head>
  <body>
    <div id="chart" style="width:400px; height:300px;"></div>
    <script>
      $(function(){
        var data=[[100, 100, 75, 99, 89, 100, 85, 95, 77],
                  [78, 55, 66, 60, 80, 75, 80, 83, 71],
                  [45, 49, 53, 56, 72, 50, 75, 78, 67]];
        var options={title: "月收盤價",
                     axes: {xaxis: {label: "月份",
                                    pad: 2 
                                    },
                            yaxis: {label: "價格"}
                            }
                     };
        $.jqplot('chart', data, options);
        });
    </script>
  </body>
</html>

結果如下 :




空隙變兩倍, 所以 X 軸刻度變成從 -4 到 14 了.

其實控制坐標軸起始點除了 pad 屬性外還可以用 min 與 mix 屬性來設定, 只要將其分別設為資料的邊界即可消除空隙了, 例如將範例 3 的 X 軸 xaxis 加上 min 與 max 屬性 :


測試 6 : 用 min 與 max 屬性去除資料邊界與座標軸上下限之間的空隙 [看原始碼]


<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta http-equiv="cache-control" content="no-cache">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.css" rel="stylesheet">
    <style>
    </style>
  </head>
  <body>
    <div id="chart" style="width:400px; height:300px;"></div>
    <script>
      $(function(){
        var data=[[100, 100, 75, 99, 89, 100, 85, 95, 77],
                  [78, 55, 66, 60, 80, 75, 80, 83, 71],
                  [45, 49, 53, 56, 72, 50, 75, 78, 67]];
        var options={title: "月收盤價",
                     axes: {xaxis: {label: "月份",
                                    min: 1,
                                    max: 9
                                    },
                            yaxis: {label: "價格",
                                    min: 40,
                                    max: 100 
                                    }
                            }
                     };
        $.jqplot('chart', data, options);
        });
    </script>
  </body>
</html>

結果如下 :




雖然空隙消除了, 但坐標軸刻度卻變成浮點數, 月份變成有小數點, 原因是刻度數目變少了, 在上面範例 4 中 X 軸有 9 個刻度; Y 軸則有 7 個刻度, 現在卻變成 X 軸只有 7 個, 而 Y 軸只有 5 個, 補救的辦法是用 numberTicks 來設定刻度數目, 例如 :


測試 7 : 用 numberTicks 設定坐標軸刻度數目 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta http-equiv="cache-control" content="no-cache">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.css" rel="stylesheet">
    <style>
    </style>
  </head>
  <body>
    <div id="chart" style="width:400px; height:300px;"></div>
    <script>
      $(function(){
        var data=[[100, 100, 75, 99, 89, 100, 85, 95, 77],
                  [78, 55, 66, 60, 80, 75, 80, 83, 71],
                  [45, 49, 53, 56, 72, 50, 75, 78, 67]];
        var options={title: "月收盤價",
                     axes: {xaxis: {label: "月份",
                                    min: 1,
                                    max: 9,
                                    numberTicks: 9   
                                    },
                            yaxis: {label: "價格",
                                    min: 40,
                                    max: 100,
                                    numberTicks: 7 
                                    }
                            }
                     };
        $.jqplot('chart', data, options);
        });
    </script>
  </body>
</html>

結果如下 :




這與上面範例 4 繪製之圖形完全一樣. 另外一個方式是利用 ticks 屬性用一個陣列指定要顯示哪些刻度值, 例如 :


測試 8 : 用 ticks 屬性指定要顯示那些刻度值 [看原始碼]

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta http-equiv="cache-control" content="no-cache">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/jqplot@1.0.9/jquery.jqplot.min.css" rel="stylesheet">
    <style>
    </style>
  </head>
  <body>
    <div id="chart" style="width:400px; height:300px;"></div>
    <script>
      $(function(){
        var data=[[100, 100, 75, 99, 89, 100, 85, 95, 77],
                  [78, 55, 66, 60, 80, 75, 80, 83, 71],
                  [45, 49, 53, 56, 72, 50, 75, 78, 67]];
        var options={title: "月收盤價",
                     axes: {xaxis: {label: "月份",
                                    min: 1,
                                    max: 9,
                                    ticks: [1,2,3,4,5,6,7,8,9]   
                                    },
                            yaxis: {label: "價格",
                                    min: 40,
                                    max: 100,
                                    ticks: [40,50,60,70,80,90,100]   
                                    }
                            }
                     };
        $.jqplot('chart', data, options);
        });
    </script>
  </body>
</html>

此例用 ticks 陣列列舉要顯示之刻度值, 結果如下 :




但是 X, Y 坐標軸刻度卻變成浮點數!

沒有留言 :