iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 7
0
Modern Web

資料視覺化!D3入門到實戰系列 第 7

Day7 比例與座標軸_理解D3中的比例(Scale)

  • 分享至 

  • xImage
  •  

為什麼需要比例?

相信大家在國中小的地理課一定有學過地圖,地圖中最重要也是容易讓人混淆的就是比例尺。思考一下,要如何在小小的A4紙當中塞進一個台灣?
比例就是為了解決這個問題,將台灣大小等比例縮小到可以放在A4當中,並說明地圖上的一公分代表的是實際的多長,那就是比例尺的功用。

在畫普通的圖表也是如此,如果要畫一個簡單的長條圖,前面我們都是已經定義好svg畫布的大小,假設是400 * 600,若有一筆資料的值是1000,那不就會遠遠超出畫布範圍了呢?

D3中的scale

D3提供了scale的方法來讓你給的一組數據轉換輸出成另一組適合的數據,轉換方式又會因為資料特性而有不同,這邊先來介紹比較常用的linear,也就是線性比例。

線性比例(Linear Scale)

這張圖的中間像工廠的地方就是d3的scale,實際大小在經過中間的轉換以後能得到在畫布上應該要顯示的大小,除了數字大小以外,d3也可以讓數字轉換成顏色的色碼,供我們可以做熱力圖等圖表。

直接來寫程式看看!

// 先做出轉換用的function,就是圖中中間的工廠
const y = d3.scaleLinear()
            .domain([30, 1000]) //實際的最小值為30、最大值為1000
            .range([0, 400]) //畫布長度的最小值為0、最大值為400

console.log(y(500)); //輸入實際的500,在畫布上為193.8144

現在你知道該怎麼做出scale的function了,那該怎麼應用在圖表上?

有一筆資料[874, 291, 30, 500, 1000],請畫出長條圖。

<svg width="600" height="400" style="border: 1px solid black"></svg>
<script src="http://d3js.org/d3.v5.min.js"></script>
<script>
  const data = [874, 291, 30, 500, 1000];
  const svg = d3.select('svg');
  const y = d3
    .scaleLinear()
    .domain([0, d3.max(data)])
    .range([0, 400]);

  const rects = svg
    .selectAll('rect')
    .data(data)
    .enter()
    .append('rect')
    .attr('x', (d, i) => {
      return i * 60
    })
    .attr('height', (d, i) => {
      return y(d);
    })
    .attr('width', 40)
    .attr('fill', 'black');
</script>

分段比例(Band Scale)

在畫上一張的長條圖時你有沒有覺得很奇怪,如果今天資料筆數每一次都不一樣,那我怎麼知道每個長條圖寬度要放多少?x是多少?彼此又要離多遠?

這時候就要用到d3的分段比例了,用法跟線性的很類似,使用的情境多在於圖表當中非線性的資料列。

廢話不多說,直接來實作看看:

<svg width="600" height="400" style="border: 1px solid black"></svg>
<script src="http://d3js.org/d3.v5.min.js"></script>
<script>
  const data = [
    { value: 874, name: '1' },
    { value: 291, name: '2' },
    { value: 30, name: '3' },
    { value: 500, name: '4' },
    { value: 1000, name: '5' }
  ];
  const svg = d3.select('svg');
  const y = d3
    .scaleLinear()
    .domain([
      0,
      d3.max(data.map((e) => e.value))
    ])
    .range([0, 400]);
   
  //原本的x、width等都是寫死的,這次我們做一個x scale的function
  const x = d3
    .scaleBand()
    .domain(data.map((e) => e.name))
    .range([0, 600])
    .paddingInner(0.3)
    .paddingOuter(0.3);

  const rects = svg
    .selectAll('rect')
    .data(data)
    .enter()
    .append('rect')
    .attr('x', (d, i) => {
      return x(d.name);
    }) //將name直接丟進去x()
    .attr('width', x.bandwidth) // 寬度直接使用它幫我們算好的
    .attr('height', (d, i) => {
      return y(d.value);
    })
    .attr('fill', 'black');

如此一來就得到x平均分配的圖表呢!


上一篇
Day6 理解D3的數據處理
下一篇
Day8 比例與座標軸_利用比例實作座標軸(Axis)
系列文
資料視覺化!D3入門到實戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言