資料視覺化是網頁上常用的媒材,在本篇文章中我們將實際操作在jQuery/ Vue/ D3這三種框架下如何繪製出好用的動態長條圖,同時分析各個框架的優勢與劣勢,讓我們繼續往下看吧!
首先讓我們對長條圖有個初步了解。長條圖多用於呈現相同性質但不同量級的資料,例如比較美國、台灣、日本這三個國家的人口數。用程式碼撰寫一個長條圖主要分為三個步驟:
- 資料整理,通常會用陣列表現相同性質且不斷重複的資料。
- 在網頁上產生相對應的物件(長條方塊)。
- 針對每個長條方塊設定他的屬性,例如:改變物件的高度、弧度、間距……等屬性。
我們將以Code Pen做為本次實作的平台,這是一個可以在創作的同時即時看到程式碼運作狀況的線上程式碼編輯器,只要簡單註冊就可以使用囉!
主要會用到的知識:
- HTML (Pug), CSS (Sass)與JavaScript/ jQuery的基礎觀念
- Vue框架概念
- D3框架概念
如果想搭配直播影片一起實作,請往這邊走👉 https://www.youtube.com/watch?v=o50XYczmoP0
框架一:jQuery
相信大家對jQuery都滿熟悉的,它的特性就是抓一個特定條件的東西,去修改他特定條件的屬性。
首先,在code pen上開一個新的pen,將HTML的預處理器設定成Pug、CSS的預處理器設定成Sass、jQuery的CDN掛入JS。
接著來準備一組做為圖表資料的陣列。命名一個陣列為datas
,運用JS的for迴圈,設定一個從1-10重複10遍的變數i,同時運用函數Math.random()
每次推入一個隨機的變數,用console.log印出datas陣列內的資料。
要產生圖表,需要製作一個放置長條圖、資料的容器,在HTML新增一個class為graph
的div,在CSS針對graph的width, height, border進行屬性的設定增加可視性。
接著做進一步的資料處理,運用JS的forEach
將陣列datas內的每一筆資料單獨取出(ES6簡化function為箭頭函式)給他一個參數index
,console.log印出index, obj,即可看到陣列內單獨的資料和標號用的index。
溫馨提醒:ES6中簡化function為箭頭函式()=>{}的寫法不是每個瀏覽器都吃,記得搭配webpack做轉換唷。
為了產生對應資料的長條圖,在forEach的迴圈內我們命名一個變數bar
,bar是'<div class="bar"></div>'
的HTML(注意單引號與雙引號的使用),用jQuery選取graph,利用語法append()
在被選取的元素结尾插入bar的長條圖。
在CSS針對bar做width, border的屬性設定,在graph下屬性display: flex
讓每個長條可以排排站。
接下來要替他們長不同的身高、上不同的顏色。首先在graph利用CSS flex的屬性align-items: flex-end讓長條方塊置底,在bar給每個長條margin-right: 10px
。
那要如何指定高度和顏色呢?我們利用jQuery選擇器的特性$(bar)
把它命名為變數element
,接著修改他CSS的height和background-color。由於obj為1-10的亂數,在高度呈現上的級距不明顯,所以把obj*20讓他的高度凸顯出來。
而CSS的顏色屬性是由rgb數值在0-255之間決定,如果只在1-10之間浮動的話會黑壓壓的一片,所以我們命名一個變數為color_val
,利用語法parseInt()
將obj轉成整數後再上15,這樣深淺鮮明、高度差異的長條圖就出現啦。
完成了靜態的長條圖,離動態更新長條圖就不遠了。由於接下來會比較複雜所以貼出JS的完整code給大家參考,步驟分為以下:
- 命名一個新的陣列為
elements
,用來儲存先前產生出的實體物件(變數element
),利用elements.push(element)
直接推進去。 - 利用語法
setInterval()
規定每500豪秒更新長條圖一次。 - 更新的動作利用函式generateData()來進行,把它想成一組亂數產生器,所以一樣命名一個陣列
temp
,把亂數塞進去。 - 接著讓
datas = generateData();
亂數更新一坨拉庫資料,有資料後就可以按照資料更新物件(長條方塊),因為剛剛把亂數產生包在陣列裡面了,所以記得先做初始化。運用forEach把每個物件抓出來玩一遍,根據對應的資料更新他的高度和背景顏色所以使用datas[index]
,第一筆資料對應第一個物件、第二筆資料對應第二個物件。
這樣我們就有一個會變化的長條圖了(撒花),但是否覺得變換瞬間有點卡卡的?只要在bar的CSS設定transition: 0.5s
就可以解決囉!
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); } datas = generateData(); //function初始化 console.log(datas); datas.forEach((obj, index)=>{ console.log(index, obj); var bar = '<div class="bar"></div>'; var color_val = parseInt(obj)*15; var element = $(bar); element.css("height", obj*20+"px") .css("background-color", "rgb("+color_val+","+color_val+","+color_val+")") $(".graph").append(element); elements.push(element); }); //更新 setInterval(()=>{ datas = generateData(); elements.forEach((element,index)=>{ var color_val = parseInt(datas[index])*15; element.css("height", datas[index]*20+"px") .css("background-color", "rgb("+color_val+","+color_val+","+color_val+")") }); },500);
最後一步是新增每個長條方塊所對應的數值,最快速的方法就是直接把數值包在長條bar裡面,然後使用CSS position的定位方法將數值定在長條方塊的下方。
把文字包在長條內var bar = '<div class="bar"><div class="text"></div></div>';
利用jQuery children選取element的小孩".text"
,用語法toFixed(1)
取到小數點第1位。在下方setInterval的更新處重複ㄧ樣的步驟,記得把變數名稱obj修改成datas[index]
。
element.children(".text").text(obj.toFixed(1))
接著在CSS針對bar和text的定位做設定,就可以看到長條圖表下方出現數值了。
.bar position: relative .text position: absolute bottom: -30px
做到這裡你有沒有發現我們一直在做一件重複的事情?沒錯,就是針對實體物件的數值做修改。用jQuery寫圖表就有點像用一個簡單的錘子蓋房子,從建造到調整都需要針對每個DOM物件去做手動修改,土炮且自立自強。
在下一篇文章中我們會講到另外兩個框架:Vue和D3,相較於如此「人工」的jQuery,這兩個框架比較偏自動化,就讓我們下次見囉~
課程推薦
老闆在Hahow好學校開了兩門課,其中,動畫互動網頁程式入門(HTML/CSS/JS)以簡單例子帶你入門網站的基礎架構及開發,用素材刻出簡單有趣又美觀的網頁和動畫,享受做出獨一無二的網頁所帶來的成就感,在職場上與設計師和工程師合作無間。
打好基本的互動網頁基礎之後,可以進階動畫互動網頁特效入門(JS/CANVAS),紮實掌握JavaScript 程式與動畫基礎以及進階互動,整合應用掌控資料與顯示的Vue.js前端框架,完成具有設計感的互動網站。期待在課程裡見到你!