2020-04-22

【WEB程式】以 Chartjs 繪製圖表

Chartjs 是一套免費且開放原始碼(採用 MIT 授權) 的網頁圖表繪製套件,可繪製 6 種基本圖表:
line(折線圖/線條圖)、bar(條狀圖,直/橫條)、radar(雷達圖)、doughnut & pie(圓餅圖/甜甜圈圖)、polar area(極座標圖餅圖/南丁格爾玫瑰圖/雞冠花圖/風花圖)、bubble(氣泡圖)

2 種衍伸圖表(不知道這兩種圖表的中文名稱):
scatter(散佈圖)area

還可以上述 8 種圖表混合使用。


chartjs 上傳到您的網站內的指定目錄下,在本例為 /plugin/

PHP 網頁內容
  1.  
  2. ...
  3. ...
  4. <head>
  5. <script src="/jquery/jquery-1.11.3.min.js"></script> <!-- jQuery 不是必需, 但我不熟純 javascript -->
  6. <script src="/plugin/chartjs/Chart.bundle.min.js"></script>
  7. <script src="/plugin/chartjs/Chart.min.js"></script>
  8. <script src="/plugin/chartjs/chartjs-plugin-zoom.min.js"></script>
  9. <script src="/plugin/chartjs/utils.js"></script>
  10. <script src="/plugin/chartjs/moment-with-locales.min.js"></script>
  11. </head>
  12. <!-- 設定圖表尺寸 -->
  13. <style>
  14. .chart
  15. {
  16. height:100; width:45%; margin: 20px;
  17. }
  18. </style>
  19.  
  20. ...
  21. ...
  22.  
  23. <body>
  24. <?php
  25.  
  26. // 宣告存放數據的陣列
  27. $aExname = array(); // 考試名稱
  28. $aDlday = array(); // 單日下載
  29. $aDlcnt = array(); // 總下載數
  30. $aExamday = array(); // 單日練習
  31. $aExamcnt = array(); // 總練習數
  32.  
  33. // 建立資料庫連線, 並取得資料
  34. $pdoStat = $pdo->prepare($sql);
  35. $pdoStat->execute();
  36. $rs = $pdoStat->fetchAll();
  37. if(count($rs)>0)
  38. {
  39. foreach($rs as $row)
  40. {
  41. // 將各欄位值存入陣列
  42. array_push($aExname, $row['exname']); // 考試名稱
  43. array_push($aDlday, $row['dlday']); // 單日下載
  44. array_push($aDlcnt, $row['dlcnt']); // 總下載數
  45. array_push($aExamday, $row['examday']); // 單日練習
  46. array_push($aExamcnt, $row['examcnt']); // 總練習數
  47. }
  48. // 將陣列自 PHP 轉出變為 javascript 陣列
  49. // str_pad() 沒什麼作用, 只是讓轉出的 HTML 原始碼易於閱讀而已
  50. echo str_pad(" ", 28)."<script language='javascript'>\n";
  51. echo str_pad(" ", 28).'var aExname = '.json_encode($aExname).";\n"; // 考試名稱
  52. echo str_pad(" ", 28).'var aDlday = '.json_encode($aDlday).";\n"; // 單日下載
  53. echo str_pad(" ", 28).'var aDlcnt = '.json_encode($aDlcnt).";\n"; // 總下載數
  54. echo str_pad(" ", 28).'var aExamday = '.json_encode($aExamday).";\n"; // 單日練習
  55. echo str_pad(" ", 28).'var aExamcnt = '.json_encode($aExamcnt).";\n"; // 總練習數
  56. echo str_pad(" ", 28)."</script>\n";
  57. }
  58. ?>
  59.  
  60. // 左, 右 放置 2 個直條圖
  61. <div class="chart" style="float:left;">
  62. <!-- 各考試單日統計 -->
  63. <canvas id="chartDay" />
  64. </div>
  65.  
  66. <div class="chart" style="float:right;">
  67. <!-- 各考試總計 -->
  68. <canvas id="chartTotal" />
  69. </div>
  70.  
  71. <script language='javascript'>
  72. var ctx1 = $("#chartDay");
  73. var myChart1 = new Chart(ctx1,
  74. {
  75. type: 'bar', // 指定圖表為直條圖
  76. data: {
  77. datasets: [{
  78. data: aExamday,
  79. label: "單日練習",
  80. borderColor: window.chartColors.green, // 有這幾個基本顏色可選:red, orange, yellow, green, blue, purple, grey
  81. backgroundColor: window.chartColors.green
  82. },
  83. {
  84. data: aDlday,
  85. label: "單日下載",
  86. borderColor: window.chartColors.red, // 折線顏色
  87. backgroundColor: window.chartColors.red // legend 色塊顏色
  88. }
  89. ],
  90. labels: aExname
  91. },
  92. options: {
  93. animation: {
  94. duration: 0, // 不以動畫方式畫線
  95. },
  96. title: { // 圖表標題
  97. display: true,
  98. text: "各考試單日統計",
  99. fontSize: 18
  100. },
  101. legend:{ // 各色直條圖所代表的群體
  102. position: 'top' // 置於圖表上方, 另可置於 bottom, left, right
  103. },
  104. scales: {
  105. yAxes: [{ // Y 軸的樣式
  106. type: 'linear',
  107. position: 'left',
  108. ticks: { // 加上千位符
  109. userCallback: function(value, index, values)
  110. {
  111. return value.toLocaleString();
  112. }
  113. }
  114. }]
  115. },
  116. tooltips: { // 直條內的提示數字加上 千位符
  117. callbacks: {
  118. // this callback is used to create the tooltip label
  119. label: function(tooltipItem, data)
  120. {
  121. var dataLabel = data.labels[tooltipItem.index];
  122. var value = ': $' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index].toLocaleString();
  123.  
  124. if (Chart.helpers.isArray(dataLabel))
  125. {
  126. dataLabel = dataLabel.slice();
  127. dataLabel[0] += value;
  128. }
  129. else
  130. {
  131. dataLabel += value;
  132. }
  133. return dataLabel;
  134. }
  135. }
  136. },
  137. onClick: function (event, arr)
  138. {
  139. // 可以指定點擊某個直條時,跳轉至指定的網頁
  140. switch(arr[0]._view['label'])
  141. {
  142. case '條件1': window.location.href = "下個網頁";
  143. break;
  144. case '條件2': window.location.href = "下個網頁";
  145. break;
  146. ...
  147. ...
  148. }
  149. }
  150. }
  151. });
  152.  
  153.  
  154. /////////////////
  155. var ctx2 = $("#chartTotal");
  156. var myChart2 = new Chart(ctx2,
  157. {
  158. type: 'bar',
  159. data: {
  160. datasets: [{
  161. data: aExamcnt,
  162. label: "總練習數",
  163. borderColor: window.chartColors.green,
  164. backgroundColor: window.chartColors.yellow
  165. },
  166. {
  167. data: aDlcnt,
  168. label: "總下載數",
  169. borderColor: window.chartColors.blue,
  170. backgroundColor: window.chartColors.blue
  171. }
  172. ],
  173. labels: aExname
  174. },
  175. options: {
  176. animation: {
  177. duration: 0, // 不以動畫方式畫線
  178. },
  179. title: {
  180. display: true,
  181. text: "各考試總計",
  182. fontSize: 18
  183. },
  184. legend:{
  185. position: 'top'
  186. },
  187. scales: {
  188. yAxes: [{
  189. type: 'linear',
  190. position: 'left',
  191. ticks: { // 加上千位符
  192. userCallback: function(value, index, values)
  193. {
  194. return value.toLocaleString();
  195. }
  196. }
  197. }]
  198. },
  199. tooltips: { // 直條內的提示數字加上 千位符
  200. callbacks: {
  201. // this callback is used to create the tooltip label
  202. label: function(tooltipItem, data)
  203. {
  204. var dataLabel = data.labels[tooltipItem.index];
  205. var value = ': $' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index].toLocaleString();
  206.  
  207. if (Chart.helpers.isArray(dataLabel))
  208. {
  209. dataLabel = dataLabel.slice();
  210. dataLabel[0] += value;
  211. }
  212. else
  213. {
  214. dataLabel += value;
  215. }
  216. return dataLabel;
  217. }
  218. }
  219. },
  220. onClick: function (event, arr)
  221. {
  222. // 可以指定點擊某個直條時,跳轉至指定的網頁
  223. switch(arr[0]._view['label'])
  224. {
  225. case '條件1': window.location.href = "下個網頁";
  226. break;
  227. case '條件2': window.location.href = "下個網頁";
  228. break;
  229. ...
  230. ...
  231. }
  232. }
  233. }
  234. });
  235. </script>
  236.  
  237. ...
  238. ...
  239. </body>
  240. </html>
  241.  


圖表成果如下:
* 因圖表寬度較小,因此 chartjs 自動隱藏某些考試名稱,以下圖為例,只顯示單數欄的考試名稱
* 滑鼠至直條內時會顯示相應的數值
* 不知道是不是沒摸索到顏色的配置方法,Chartjs 不會自動幫您配顏色,所以您必須要自己先建立一個顏色陣列,要用時,再到陣列取顏色值;或是自己以亂數產生顏色值,只是以亂數產生,有時會碰到相臨 2 個顏色太相近的窘境。



還有另一套圖表套件 ---- ZingChart,老人家自己覺得蠻好用又功能強大,但下載免費版使用時,圖表會強制顯示該公司的 LOGO 打廣告。

若不在意該公司的 LOGO 老人家倒是蠻推 ZingChart 的,因為好上手,學習曲線低;但如果不想顯示 LOGO......就付費吧(老人家的長官就不希望看到 LOGO,所以後來採用 Chartjs)。


最新發現! Apache 基金會的 Apache ECharts,開放源碼,而且免費,也不難學習,更推!!

 


相關筆記 ----

【WEB程式】以 Apache ECharts 繪製圖表

沒有留言:

張貼留言