本篇大綱:window.resize、RWD 圖表、軸線刻度數量隨畫面變化增減
前兩篇看完比例尺跟軸線後,現在D3的知識拼圖就只差最後這塊啦!今天我們要學的是怎麼畫「響應式圖表
」,也就是讓圖表在畫面放大或縮小時,都能夠隨著畫面去調整圖表的大小!這個章節也是輕鬆簡單的單元,只是有比較多細節需要設定,一起來看一下吧~
在之前的篇章中,我們建立的 svg 都有固定的寬高,這樣的圖表在網頁上看很OK,但如果要在手機或平板上看,就會發現圖表太大無法看
為了使用者在手機或平板上也能夠看圖表,因此我們要對圖表進行一些設定,讓它變成下面這樣
要設定RWD圖表的話,我們需要使用到 window 的 onresize 事件,每當 window 監聽到畫面大小有變化時,就會觸發設定的方法。首先,我們先用d3的選取器把window選起來接著使用 selection.on( )的方法監聽 resize 事件,並設定畫面 resize 的時候要做什麼事
d3.select(window).on('resize', function(){
console.log('畫面變化')
});
這樣一來,畫面大小變化時,就會觸發我們設定好的功能啦(請看畫面右方的 console 訊息)~
接著,我們要來設定外容器的高度。如果我們的 svg 是包在div中的話,就是設定這個div的寬度。
<div class="RWDChart">
<svg>......</svg>
</div>
我們使用 css 把外容器的寬度設定成百分比,讓外容器能隨著畫面變化而縮放
.RWDChart{
width: 80%
}
再來設定 svg 的寬高吧!之前我們的 svg 寬高都是直接寫死
const width = 500,
height = 400;
const svg = d3.select('.simpleChart')
.append('svg')
.attr('width', width)
.attr('height', height)
現在我們要改變作法,用外容器RWD的寬度來設定 svg 的寬高。
svg 寬度
:用 d3.selection 抓到外容器的寬度,接著用 parseInt( )將這個寬度賦予給 rwdSvgWidth 變數,接著將這個變數設定成 svg 的寬度svg 高度
:用剛剛設定好的 rwdSvgWidth 來設定 rwdSvgHeight 變數,並將 rwdSvgHeight 設定成 svg 的高度const rwdSvgWidth = parseInt(d3.select('.RWDChart').style('width')),
rwdSvgHeight = rwdSvgWidth*0.8,
margin = 30,
bandWidth = 20
const svg = d3.select('.RWDChart')
.append('svg')
.attr('width', rwdSvgWidth)
.attr('height', rwdSvgHeight);
這樣一來,我們的 svg 寬高就能夠隨著畫面縮放而增減啦!
現在我們可以開始繪製RWD的圖表啦!由於這邊的重點是RWD,因此繪製圖表的程式碼就先不呈現,而是著重在要怎麼讓圖表RWD上
function RWDChart(){
const rwdSvgWidth = parseInt(d3.select('.RWDChart').style('width')),
rwdSvgHeight = rwdSvgWidth*0.8,
margin = 30,
bandWidth = 20
const svg = d3.select('.RWDChart')
.append('svg')
.attr('width', rwdSvgWidth)
.attr('height', rwdSvgHeight);
// 以下為繪製圖表的程式碼
// ......
// ......
}
RWDChart() // 一開始要先執行一次,才能在畫面開始時建立圖表
d3.select(window).on('resize', RWDChart); // 接著要在每次畫面變化時都重新渲染圖表
但這時候出現一個新的問題:每次畫面變化重新渲染圖表時,我們的圖表就會一直不停重複增加!!
這是因為畫面變化時會重新渲染圖表,但原本的圖表也都還存在,導致圖表不停的往下增加。因此我們要加上一段程式,讓每次圖表繪製前,都會刪除掉原本的圖表
function RWDChart(){
**d3.select('.RWDChart svg').remove(); // 刪除前一次建立的圖表**
const rwdSvgWidth = parseInt(d3.select('.RWDChart').style('width')),
rwdSvgHeight = rwdSvgWidth*0.8,
margin = 30,
bandWidth = 20
const svg = d3.select('.RWDChart')
.append('svg')
.attr('width', rwdSvgWidth)
.attr('height', rwdSvgHeight);
// 以下為繪製圖表的程式碼
// ......
// ......
}
RWDChart() // 一開始要先執行一次,才能在畫面開始時建立圖表
d3.select(window).on('resize', RWDChart); // 接著要在每次畫面變化時都重新渲染圖表
這樣一來,就可以解決圖表重複出現的問題啦~
最後,我們要講一個有趣的功能~當圖表隨畫面縮小時, 有時候坐標軸的刻度會因為圖表縮小而重疊在一起
為了不讓刻度重疊,我們要在圖表縮小時減少刻度的數量。這時候就要用到 window.innerWidth 跟 ticks 設定的方法啦!
先來設定一個 tickNumber 的變數,並且:
最後將 tickNumber 作為參數帶給 .ticks( ) 這個方法。由於這邊不是在講解如何建立圖表,因此就只把刻度RWD的程式碼擷取出來。想看完整程式碼的人請直接到下方的 Giithub 頁面查看~
// rwd X軸的刻度
let tickNumber = window.innerWidth > 450 ? null : 5;
xAxis = d3.axisBottom(xScale)
.ticks(tickNumber)
.tickFormat(function (d) {
//調整標籤樣式
return `${d} 元`;
})
這樣就完成囉!
今天的內容就到這邊。這樣一來,D3 繪圖的重要知識都已經全部講解完畢啦!接下來我們就要運用這幾天學到的知識去繪圖囉!一天一張圖表,我來了!!
最後附上本章的程式碼與圖表 Github 、 Github Page,需要的人請自行取用~