2023年1月3日 星期二

D3.JS 長條圖範例


D3 是客製化的圖表加上動態的生動的圖表,讓人更賞心稅目,但也聽說入手不易,常常搞不懂有哪些API 可以使用,官方文件有些難閱讀等等,線上總是有很多高手有提供範利,其中我也是以新手的身份來掀開d3這神祕的面紗吧! 參考範例來源

https://gist.github.com/kurotanshi/949bc9cc6e53a2518bdedb438be0de79 

一、 引用d3的js 要引用d3要注意版本喔,不一定相容舊的版本… 

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script>

二、 新增svg的畫布

 <div id="content">
   <svg class="svg"></svg>
</div>

 三、 資料收集 (要用json格式,才可以用在d3的圖表上) 

 
 var data = [
  {
    "region": "台北",
    "unit": 46.40977922,
    "price": 91086.0211,
    "unit_price": 2570.210781
  },
  {
    "region": "高雄",
    "unit": 32.4142328,
    "price": 63651.00159,
    "unit_price": 2173.609712
  },
  {
    "region": "台中",
    "unit": 29.51372024,
    "price": 69658.03571,
    "unit_price": 2125.218562
  },
  {
    "region": "彰化",
    "unit": 34.4416108,
    "price": 73852.80682,
    "unit_price": 1970.313951
  },
  {
    "region": "南投",
    "unit": 26.92638889,
    "price": 48446.94739,
    "unit_price": 1893.854422
  },
  {
    "region": "新竹",
    "unit": 43.1695172,
    "price": 85949.14021,
    "unit_price": 1813.571443
  },
  {
    "region": "花蓮",
    "unit": 31.25626667,
    "price": 50813.33333,
    "unit_price": 1694.577185
  },
  {
    "region": "台北市",
    "unit": 39.56244844,
    "price": 63101.91847,
    "unit_price": 1655.043669
  },
  {
    "region": "新北市",
    "unit": 33.11200327,
    "price": 47315.73129,
    "unit_price": 1501.26019
  },
  {
    "region": "宜蘭",
    "unit": 36.26450183,
    "price": 48655.03391,
    "unit_price": 1489.35871
  },
  {
    "region": "花蓮",
    "unit": 42.60729097,
    "price": 55846.34104,
    "unit_price": 1427.583885
  },
  {
    "region": "雲林",
    "unit": 37.96167857,
    "price": 44534.22619,
    "unit_price": 1293.030994
  }
];

 四、 宣告svg 畫布的大小範圍

使用 translate 可以讓圖形在 x 軸或 y 軸進行位移 ( 中括號為不是必須的值 ),所謂的位移是指原本的坐標加上多少。

var svg = d3.select('.svg');
 
  var margin = 80,
      width = 960 - margin * 0.7,
      height = 500 - margin * 2-30;
   
  svg.attr({
    "width": width + margin,
    "height": height + margin * 2,
    "transform": "translate(" + margin + "," + margin + ")"
  });    

 linear 意即會有等比例的縮放大小

.domain 輸入的資料來源 (0, N)
.range   
輸出的資料範圍(0,N) 

白話文的意思~ 如果你的資料來源介於(0,990) , 但輸出的數值範圍(0,100), d3的函數就會自動把值等比例的縮小至(0~100)的區間喔


var xScale_price = d3.scale.linear()
    .domain([0, data.length])
    .range([0, width]);
 
  // y 軸比例尺 2 繪製座標軸用
  var yScale2_price = d3.scale.linear()
    .domain([0, 100000])
    .range([height, 0]);

Asix : 繪製刻線
.scale    
比例尺
.orient  畫線的位置  (top  bottom   left  rieght )
.ticks     刻度的數量
.tickFormat : 設定資料格式 / 顯示刻度

 // x 軸
  var xAxis = d3.svg.axis()
    .scale(xScale_price)
    .orient("bottom")    
    .ticks( data.length )
    .tickFormat(function(i){      
      return (data[i]) ?  data[i].region : '';   // 這裡控制坐標軸的單位
    });

  // y 軸
  var yAxis = d3.svg.axis()
    .scale(yScale2_price)
    .orient("left");

新增的dom元件,將圖表繪製上畫面上

// 繪製 x 軸
  svg.append("g")
    .attr({
      "class": "x axis",
      "transform": "translate(" + margin + "," + (height + margin) + ")",
      'fill': '#ffffff'
    })
    .call(xAxis);

      // 繪製 y 軸
  svg.append("g")
    .attr({
      "class": "y axis",
      "transform": "translate(" + margin + ", " + margin + ")",
      'fill': '#ffffff'
    })
    .call(yAxis);

scale.category10   產生隨機10種顏色
selectAll                選擇dom元素 (像css語法)
data                        輸入資料來源
enter                      找出不夠資料塞入的元素筆數,再透過 append() 函式新增元素
append                   加上長方條(rect)
classed                   客製化的css 或傳入值控制css




    var xScale = d3.scale.linear().domain([0, data.length]).range([0, width]);
    var yScale  = d3.scale.linear().domain([0, 100000]).range([0, height]);
    var chartType = "price";
    var c10 = d3.scale.category10();
       // 產生長條圖
       svg.selectAll('.bar')
        .data(data)
        .enter()
        .append('rect')
        .classed('bar', true);

        svg.selectAll('.bar')
        .transition()
        .duration(700)
        .attr({
          'x': function(d, i) {
            return xScale(i) + margin
          },
          'y': function(d, i) {
            return height - yScale(d[chartType])+ margin;
          },
          'width': '5%',
          'height': function(d, i) {
            return yScale(d[chartType]);
          },
          'fill': function(d, i){
            return c10(i);
          },
          "transform": "translate(" +  width * (0.02) + ", " + 0 + ")",
        });


示易圖