資料視覺化的動態長條圖製作(下):Vue/ D3(直播筆記)

在上篇我們講解了如何使用jQuery製作網頁上常用的動態長條圖,在本篇文章中我們將實際操作另外兩種框架:Vue/ D3的製作方法。還沒看上一篇的快快補唷👉 資料視覺化的動態長條圖製作(上):jQuery(直播筆記)

https://i.imgur.com/cEEkxZo.gif

主要會用到的知識:

  1. HTML (Pug), CSS (Sass)與JavaScript/ jQuery的基礎觀念
  2. Vue框架概念
  3. D3框架概念

如果想搭配直播影片一起實作,請往這邊走👉 https://www.youtube.com/watch?v=o50XYczmoP0


框架二:Vue

Vue就像你雇用了一位負責代換抄寫的小幫手,你所需要做的就是提供資料的類型和處理方式,小幫手就會自動化地填入。

首先將剛剛jQuery完成的圖表直接fork,fork是幫你複製一個新的pen,修改時不會動到原本的東西。在JS的設定裡面代入Vue。

https://i.imgur.com/uadgAsW.png

由於Vue的特性是在HTML寫模板,然後利用JS帶入資料,所以在HTML裡面新增.bar,JS的部分先把height和background-color的設定複製起來,整個forEach的部分拿掉,//更新的地方暫時註解掉。

https://i.imgur.com/OWM6T9l.png

接著把Vue這個小幫手請出來幫我們抄寫跟產生DOM物件,告訴他工作的範圍後,也要指定原本的資料datas,在HTML告訴他希望他幫我們重複打.bar這個木樁10遍,同時把木樁的數值也打上去,用toFixed(1)取到小數點第1位。

HTML

#app.graph
  .bar(v-for="data in datas") {{data.toFixed(1)}}

JavaScript

var datas = [];
var elements = [];
function generateData(){
  var temp = [];
  for( var i=0; i<10; i++){
    temp.push(Math.random()*10+5);
  }
  return temp;
}

for( var i=0; i<10; i++){
  datas.push(Math.random()*10+5);
}

var vm = new Vue({
  el: "#app",
  data:{
    datas: datas
  }
})

接著來設定長條方塊的樣式,透過Vue可以動態地去修改CSS屬性。在HTML新增:style="gen_style(data)",gen_style()像是一個方法,指導我們的小幫手說style要用data這個資料去算一個屬性(顏色、高度)做呈現。那小幫手要如何知道gen_style這個方法的實際內容呢?我們需在JS新增一個Method:{}來告訴他。Method就像一本作業指導書,在裡面我們需要回傳一個JSON物件,用來說明CSS屬性的設定。因為rgb數值設定的關係,記得data需要先用語法parseInt()處理成整數唷。

HTML

#app.graph
  .bar(v-for="data in datas",
       :style="gen_style(data)") {{data.toFixed(1)}}

JS

var vm = new Vue({
  el: "#app",
  data:{
    datas: datas
  },
  methods:{
    gen_style(data){
      var d = parseInt(data);
      return {
        "height": data*20+"px",
        "background-color":"rgb("+data*10+","+data*10+","+data*10+")"
      };
    }
  }
})

登愣,神奇的事情發生了!我們明明沒有實際地對DOM物件做屬性指定的動作,他卻乖乖地自動產生對應資料的長條圖,這就是Vue好用的地方啦,就像你買了一台3D印表機,只要告訴他規則、資料,他就會自動幫你蓋好房子了。

https://i.imgur.com/swO9EQf.png

剛剛我們用jQuery寫了一拖拉庫來達到每500毫秒自動更新的效果,在Vue只需要告訴他vm.datas = datas;就可以完成囉。

//更新
setInterval(()=>{
  datas = generateData();
  vm.datas = datas;
},500);

總地來說Vue的自動化很高、很方便,但相對他的產出就必須follow你訂下的規則,沒辦法一個一個做特定調整。


框架三:D3

D3有點像是jQuery的強化版,只是這次你拿的不是一支小破錘子,而是課金後的超炫砲無敵錘子,除了可以根據規則做重複的事情以外,還可以針對個體做客製化調整。

我們再fork一次剛剛jQuery完成的圖表。在JS的設定裡面代入D3。

https://i.imgur.com/YHScuKG.png

剛剛在jQuery我們透過forEach把物件一個一個抓出來改,現在我們不需要單獨抓出來了所以先註解掉,取而代之的是批次抓取做修改,setInterval()的地方也暫時註解掉。

  1. select()選擇graph裡面全部的bar
  2. 資料來源是datas請來這邊找。
  3. 因為現在bar還不存在而datas有10筆,透過enter()來補齊物件跟資料差距的量。當DOM數量少於data的數量,或者壓根一個都沒有的時候,我們一般會使用enter()幫忙建立。
  4. append顧名思義就是添加的意思,透過append()新增div。
  5. attr()是負責命名這個div的class為bar。
d3.select(".graph").selectAll(".bar")
  .data(datas)
  .enter()
  .append("div")
  .attr("class", "bar")
https://i.imgur.com/VSS87CD.png

有了十個bar之後接下來就是我們的重頭戲──調整高度和顏色。高度根據資料datas(d)中的第幾筆資料(i)去做調整,乘上20讓他差距更大、可視性更好,記得加上px因為他是CSS的屬性。

.style("height",(d,i)=>(d*20+"px"))

這邊要介紹D3中的一個概念:定義比例scale.linear()。我們可以把它理解成地圖上常見的比例尺,例如台灣面積大約3萬多平方公里,要塞進一張 A4 大小的地圖根本是不可能的任務,這時候就必須要用到比例了。首先,命名一個函數為yscale做線性轉換,domain()代表「原始的資料範圍」,range()則代表「轉換後的資料範圍」。先前我們在CSS把grpah的height設定為400px,所以設定轉換後range為0-400。

var yscale= d3.scaleLinear().domain([5,15]).range([0,400])

由console的結果可見yscale現在是一個可做等比例放大的函數,就像多拉O夢的放大燈ㄧ樣,藉由yscale我們也不需要再自己手動幫d乘上20增加他的級距了。

https://i.imgur.com/QP45dn7.png

顏色也是用相同的概念處理,除了數值的放大轉換外,D3也可以幫你把數值轉成顏色。命名一個函數為color,設定轉換成白色到紅色的區間。由console的結果可見color會自動幫我們把5-15的數值轉成rgb的色碼。

var color = d3.scaleLinear().domain([5,15]).range(['white','red'])

https://i.imgur.com/VKSRSvz.png

接著就來完成我們的圖表啦,使用語法style()做高度和顏色的設定,美美的圖表就大功告成了。

d3.select(".graph").selectAll(".bar")
  .data(datas)
  .enter()
  .append("div")
  .attr("class", "bar")
  .style("height",(d,i)=>(yscale(d)+"px"))
  .style("background-color", (d)=>color(d))  

https://i.imgur.com/RfLadnF.png

體會到D3的強大了嗎?雖然Vue的效能最好,但D3的優點在於他可以批次地處理一些華麗的動畫效果,例如上面的圖表還可以添加以下幾種語法,至於圖表會如何地變動就讓大家體驗看看囉!

  .style("margin-bottom", (d)=>(200 - yscale(d)/2 + "px"))
  .transition().duration(500)
  .style("margin-bottom","0px")

最後再來個結尾小bonus,或許你也會有一樣的疑問。

讀者:「如果我想要有Vue的效率配上D3的華麗,到底該用哪一個呢?」

老闆:『爭什麼,摻在一起做成撒尿牛丸啊!』

Vue跟D3該如何結合呢?把剛剛用Vue完成的圖表叫回來,可以看到我們在height和background-color那做了一拖拉庫的處理,現在這些都可以交給D3來代勞。把剛剛在D3圖表用scaleLinear處理的程式碼貼過來,data的部分用yscale和color這兩個函數做計算,這樣就大功告成囉。

return {
        "height": yscale(data)+"px",
        "background-color": color(data)
      };

https://i.imgur.com/1j70XT6.png

想看更複雜的結合使用,請往這邊走👉 codepen實作範例:長條圖_Vue&D3

框架比較

以上就是這次如何用三種框架實作長條圖的講解,希望這個介紹會讓大家對於各框架的優劣勢更加了解,在未來的專案中可以無痛使用,讓長條圖替你的網頁畫龍點睛吧!我們下次再見囉~

課程推薦

老闆在Hahow好學校開了兩門課,其中,動畫互動網頁程式入門(HTML/CSS/JS)以簡單例子帶你入門網站的基礎架構及開發,用素材刻出簡單有趣又美觀的網頁和動畫,享受做出獨一無二的網頁所帶來的成就感,在職場上與設計師和工程師合作無間。

打好基本的互動網頁基礎之後,可以進階動畫互動網頁特效入門(JS/CANVAS),紮實掌握JavaScript 程式與動畫基礎以及進階互動,整合應用掌控資料與顯示的Vue.js前端框架,完成具有設計感的互動網站。期待在課程裡見到你!

墨雨設計banner

訂閱 Creative Coding Taiwan 電子報:

PHP Code Snippets Powered By : XYZScripts.com