Demo
- Demo:https://as60160.github.io/New-Labor-Pension-Fund/
- Code:https://github.com/as60160/New-Labor-Pension-Fund
前言
在政府資料開放平臺逛到投資理財類別時,看到新制勞工退休基金每月收益。前段時間,新聞總是提到新制勞工退休基金這幾個月的收益不錯,加上我之前也有自提退休金,就好奇這幾個月的收益到底有多好。由於這些資料直接看並不直覺,於是決定將它畫成圖表,連同相關資訊一起觀察。
簡介
藉由視覺化的方式觀察:
- 新制勞工退休基金近一年來每個月的操作收益率與保證收益率。
- 新制勞工退休基金歷年的操作收益與保證收益。
- 新制勞工退休基金投資的股票類型以及投資比例。
資料來源
資料取自於政府資料開放平臺,搜尋關鍵字為 「勞工退休基金」。
使用工具或技術
- Bootstrap
- jQuery
- Chart.js
- skrollr
過程
因為這次的練習主要在 API 的串接,所以使用 Bootstrap 來排版跟架構內容,搭配 jQuery 使用 AJAX ,再以 Chart.js 繪製圖形讓資料視覺化,最後用 skrollr 加上一點視差滾動效果,讓頁面不至於太過單調。
進行到畫表格的時候,琢磨了一下 jQuery 動態產生表格的程式碼該怎麼寫,畢竟表格用到的標籤多,而且各有其功能與意義。想到之前曾看過別人做九九乘法表的表格,就去找來看撰寫邏輯,這才將思路理清。
接著將 AJAX 載入的資料用 Chart.js 繪製出來。由於這是我第一次用 Chart.js,閱讀了 Chart.js 官方文件,以及其他開發者用 AJAX 取得的資料繪製 Chart.js 圖形的紀錄文章,歸納執行步驟如下:
- 先引用 Chart.js 的 CDN
- 在 HTML 加上
canvas
定義圖形位置 - 在 JavaScript 使用 AJAX 取得資料
- 透過 for 迴圈將取得的資料推到建立的空陣列中 (X 軸標籤、折線圖資料)
- 取得 Canvas 的內容
- 建構圖表、將資料指派到對應位置,並設置圖表的各項屬性與值
不過,範例都是一組資料,也就是說,折線圖中只有一條線,但我想放兩組資料,產生兩條線去互相比較、看走向,在官方文件中卻沒找到,一時不知道該從哪裡下手。
後來看到 Chart.js Samples 的範例中有兩條線的折線圖,去找了 GitHub 內對應的程式碼來看,才明白如果要在裡面放兩組資料,只要在 datasets 中用陣列放兩組物件,分別設置資料即可。
節錄部分程式碼整理如下:
1 | $.ajax({ |
繪製第三部分國內投資股票時,因為資料筆數多,表格不好呈現,所以只顯示折線圖。為了更好看出這些股票的投資比例高低,在繪製之前先將取得的資料進行了排序,然後才繪製圖形。
最後,因為覺得整體過於單調,所以用 skrollr 加上一點視差滾動效果。但滑鼠滾著滾著卻發現,只有「每月經營概況」那邊有反應,「年度經營概況」跟「股票類別」沒反應。
因為查了一陣子仍然看不出問題在哪裡,就到臉書的前端社團詢問。才知道這是因為在 AJAX 拿到資料繪製圖表之前,skrollr 已經完成 scroll 事件綁定,這時候 DOM 還沒有圖表的元素及高度。如果要解決這個問題,在每個 AJAX 繪圖之後加上 s.refresh()
就能看到效果了。
在這之前,有網友回饋視窗大小變化後,「年度經營概況」跟「股票類別」就會有反應。會這樣是因為視窗縮放時,skrollr 會重新計算高度,並且呼叫 refresh API。
問題與解決
製作這個作品時,我遇到的問題及解決方式整理如下:
問題一: jQuery 怎麼動態產生表格
進行到畫表格的時候,因為表格用到的標籤多,而且各有其功能與意義。所以怎麼用 jQuery 動態產生表格讓我思索了一番。
後來想起,之前曾看過別人做九九乘法表的表格,就去找來看撰寫邏輯,這才將思路理清,順手也做了一個九九乘法表出來。
參考: JavaScript與jQuery網頁設計範例教本 (電子書)
問題二:如何用 AJAX 取得的資料繪製 Chart.js 折線圖
第一次用 Chart.js 繪圖,所以去找官方文件研究其安裝跟使用方式。不過,官方範例中使用的圖形資料都是寫死的,而且只有一條線。但我希望政府資料開放平臺上的資料更新時,我的網頁上的圖形跟資料能透過 AJAX 隨之改變,而且裡面可以放兩組資料進去觀察。
查了幾篇其他開發者的文章後,看到最簡單的方式是先建立空陣列,用 for 迴圈將資料依序推進去,然後再將這些陣列放到 Chart.js 對應的位置。
再來要解決放兩組資料的問題,我在 Chart.js Samples 看到範例中有兩條線的折線圖,去找了 GitHub 內對應的程式碼來看,才明白如果要在裡面放兩組資料,只要在 datasets 中用陣列放兩組物件,分別設置資料即可。
參考:
- Chart.js Docs
- Chart.js line chart basic sample
- Chart.js 通过AJAX请求JSON数据来绘制图表
- Chart.js/samples/charts/line/basic
問題三:將投資股票依比重大小排序
繪製第三部分國內投資股票時,原本的資料順序是依股票類型排序的,但這樣一來,除了電子產業、金融產業,以及塑膠工業較為明顯之外,其他的股票類型難以一眼看出比例多寡。
為了更輕易看出這些股票的投資比例高低,我在繪圖之前先將取得的資料依投資比例排序。不過因為資料比較多層,一時轉不過來要怎麼將這些資料排序。
後來發現是我想得太複雜了,同樣用 sort()
搭配函式即可。只不過進行判斷時,要帶上想排序的屬性名稱,這樣就能比較那個屬性的值了。
範例:
1 | var rank = scores.sort(function(a,b){ |
參考: JavaScript 陣列元素順序重新排序 sort()
問題四:skrollr 無法正常呈現效果
加上 skrollr 後使用發現,只有「每月經營概況」那邊有視差滾動效果,「年度經營概況」跟「股票類別」沒反應。
因為查了一陣子仍然找不出問題在哪裡,就到臉書的前端社團詢問。才知道這是因為在 AJAX 拿到資料繪製圖表之前,skrollr 已經完成 scroll 事件綁定,這時候 DOM 還沒有圖表的元素及高度。如果要解決這個問題,在每個 AJAX 繪圖之後加上 s.refresh()
就能看到效果了。
去 skrollr GitHub 找了 README 文件裡,有關 refresh API 的說明來看:
裡面提到,refresh API 會重新解析所有給定的元素,如果小括號內沒有給定元素,則再次解析文檔中所有元素。
這個 API 適合在以下幾種情況使用:
- 當元素使用 “relative” 模式且需要被更新的時候
- 資料屬性是動態操作的
- 在 DOM 增加新元素,且新元素會受到 skrollr 控制
以下為蒐集到的使用 refresh API 的寫法
1 | var s = skrollr.init(); |
1 | //Add one element dynamically |
此外,有網友回饋視窗大小變化後,「年度經營概況」跟「股票類別」就會有效果了。會這樣是因為視窗縮放時,skrollr 會重新計算高度,並且呼叫 refresh API。
參考:
後記
畫成圖表之後去看,這幾個月的收益率確實節節攀升,對於勞工們來說是福音。
年度的部分可看出,較差的幾年正好逢股災,收益不好也在所難免。其它年度的收益則優於保證收益率。
而透過投資股票類別能看到,新制勞工退休基金在國內投資的股票,多半集中在起伏較大的電子產業,然後是穩定的金融保險類股。
考慮過把舊制勞退基金的資料也一起放進來,但舊制的每月收益不知為何只提供最近一個月的資料,再加上舊制歷史悠久,年度資料過多,如何呈現是個問題。其投資股票類別的比例也與新制差異不大,只有在指數股票型基金的投資比例 4.x% 相較新制的 0.2% 高很多。至於多出來的這些,主要是減少電子產業類別的比例來的。
本來想說這些資料是透過 AJAX 取得的,那麼只要政府資料開放平臺更新,這個頁面上的資料也會隨之更新、不怕過時。但是,等到次月政府資料開放平臺上的資料更新後,打開來看發現除了年度收益的資料仍在,每月收益跟股票投資類別的資料都沒有顯示出來。
到政府資料開放平臺確認後發現,次月新資料的 API 網址路徑位置和我當時取得的不同。於是,舊的不能用,新的不會來。只好改為下載 JSON 格式的檔案替代網址,以免下個月資料更新時,網頁又撈不到資料可用。
雖然政府資料開放平臺更新時,我的網頁資料無法自動隨之更新讓我覺得遺憾,但至少一開始將資料視覺化的目的有達到,也算滿足了。