iT邦幫忙

2021 iThome 鐵人賽

DAY 12
0

昨天我們繪製了長條圖的情況,今天我們再畫出所對應的數字座標軸就可以呈現這一份圖表了,目前長條圖的Y軸部分缺少的就是數值的對應,今天我們要來使用axisAPI來做出座標軸。

axisTop()、axisRight()、axisBottom()、axisLeft

首先你必須先有一個比例尺函式
來自於之前的介紹過的scale,他才能根據你所輸入的比例尺製作出對應的座標軸。
以我們之前所做的長條圖為例

let scaleY = d3.scaleLinear()
              .domain([0, 320000])
              .range([400,0]);
let axisY = d3.axisRight(scaleY);
console.log(typeof(axisY));

這時候它就會做出座標軸,昨天有提到如果我們如果將range([0,400])的話,此時座標軸的方向將會反轉,也就是最上面是0最下面是300000,所以為了讓座標軸顯示的順序與長條圖的起始點對應,所以我們必須把range()設定4000,這邊使用的方向式Right因此數字將會在軸的右邊,另外如果座標軸式水平的話,可以設置axisTop()axisBottom()

執行到let axisY = d3.axisRight(scaleY)的時候在畫面上面依然看不到這個座標軸,到這邊我們只是做出一個座標軸的函式,可以想像成這是一個設計藍圖,然後我們還沒執行它,你可以用console.log(typeof(axisY))會發現它是一個函式如下圖
https://ithelp.ithome.com.tw/upload/images/20210928/20125095qqPEVnuN8v.png

接下來我們必須帶入一個d3選取的元素到函式中渲染出來,這邊我們插入一個g標籤來群組化這個座標軸然後帶入到剛剛所建立的函式
程式碼如下

 const g = svg.append("g");
 axisY(g);

這時候你開啟開發者人員工具會發現Element欄位多了這些標籤。

https://ithelp.ithome.com.tw/upload/images/20210928/2012509588o0VYve0l.png

你嘗試著指向這些標籤你可以發現其實axis幫你做的事情是建立了一個path來代表整個軸,然後透過linetext標籤來呈現數字和數字旁邊的橫槓之後使用g標籤群組起來來呈現整個座標軸。

https://ithelp.ithome.com.tw/upload/images/20210928/20125095a2sRbgBoIQ.png

然後你就可以看到整個完整的座標軸如下

https://ithelp.ithome.com.tw/upload/images/20210928/20125095O72qrx6QMe.png

另外剛剛我們使用的是axisRight()函式,所以這些數字刻度會在座標軸的右邊我們嘗試著渲染axisBottom()函式看看。

let axisY = d3.axisBottom(scaleY);
const g = svg.append("g");
axisY(g);

這時候你會看到如下圖,刻度的數字落在軸的下方。
https://ithelp.ithome.com.tw/upload/images/20210928/20125095xP5Ve53vhK.png

ticks()函數

如果當你渲染出來的軸線需要刻度多一些的時候我們可以用ticks函數來幫我們將座標軸的刻度數量增加,當然沒有設定的時候是預設tick(10),這邊數字的意思大致是拆分十等分,但是D3Js會根據你的資料來切分,所以有可能你tick(20)他切分了18等分,並不會剛好完全等於你所切分的函式。

程式碼如下

let axisY = d3.axisRight(scaleY)
              .ticks(20);
let g = svg.append("g");
axisY(g);

https://ithelp.ithome.com.tw/upload/images/20210928/201250951dWOAE7xLa.png

tickFormat()函數

有時候我們希望使用者在觀看軸線的時候不需要這麼多的零,可以自訂義軸的文字顯示內容,這時候我就可以用tickFormat()函式來做出你想要的格式,例如我們將所有的資料除以10000之後加入"萬"
觀看以下程式碼

let axisY = d3
              .axisRight(scaleY)
              .ticks(5)
              .tickFormat(function (d) {
                return d / 10000 + "萬";
              });
const g = svg.append("g");
axisY(g);

這時候你就可以看到軸格式化成你想要的樣子如下圖

https://ithelp.ithome.com.tw/upload/images/20210928/20125095DaGCvNHb7r.png

完整程式碼如下

 const newTaipei = taipei.map((el) => {
                    el.people_total = Number(el.people_total);
                    el.area = Number(el.area);
                    el.population_density = Number(el.population_density);
                    el.site_id = el.site_id.substr(3);
                    return el;
                });
            
                let padding = 50;
                const svg = d3.select("body")
                            .append("svg")
                            .attr("width", 800)
                            .attr("height", 450);
                let min = d3.min(newTaipei, (d) => d.people_total);
                let max = d3.max(newTaipei, (d) => d.people_total);
                console.log(newTaipei);
                let scaleY = d3.scaleLinear()
                                .domain([0, 320000])
                                .range([400, 0]);

                svg.selectAll("rect")
                    .data(newTaipei)
                    .join("rect")
                    .attr("x", (d, i) => {
                        return padding + i * 60;
                    })
                    .attr("y", (d) => {
                        console.log(scaleY(d.people_total));
                        return scaleY(d.people_total);
                    })
                    .attr("width", 50)
                    .attr("height", (d) => {
                        return 400 - scaleY(d.people_total);
                    })
                    .attr("fill", "orange");
                
                
                svg.selectAll("text")
                  .data(newTaipei)
                  .join("text")
                  .text((d) => {
                      return d.site_id;
                  })
                  .attr("x", (d, i) => {
                      return padding + i * 60;
                  })
                  .attr("y", (y) => {
                      return 450 -20;
                  });
              let axisY = d3
                .axisRight(scaleY)
                .ticks(5)
                .tickFormat(function (d) {
                  return d / 10000 + "萬";
                });   
              const g = svg.append("g");
          axisY(g);
        });

最後如下圖所示

https://ithelp.ithome.com.tw/upload/images/20210928/20125095RfJnrOn8q0.png
頁面如下

githubPage

githubPpage


上一篇
D3JsDay11 觀測時候別鐵齒,拿出你的比例尺
下一篇
D3JsDay13 讓資料擁有過渡動畫,讓各位觀眾看見神話—過渡動畫
系列文
從原料到燃料,從資料到預料—資料駕馭網頁之理科的美學30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言