---
# System prepended metadata

title: "bahamut-pie - chapter3: make pies with ECharts\U0001F967"
tags: [bahamut-pie, ' side project']

---

---
tags: bahamut-pie, side project
---
# bahamut-pie - chapter3: make pies with ECharts🥧

**本文以開發時用的4.x版為準**

ECharts 是一個功能超多的圖表插件，但也因此非常複雜  
官方文件龐雜不過查起來挺方便的，如果用過其他的圖表插件，應該會熟悉一些  
我用的是 vue 版本，[vue-charts](https://github.com/ecomfe/vue-echarts)

## how it work?
ECharts 圖表可以簡單分成
- 圖表與元件的配置(圖類，顏色，軸向單位...)
- 注入的資料 dataset(series)

理解元件名詞之後大概可以看懂3~5成的文件
![配置項名詞圖解](https://echarts.apache.org/v4/zh/documents/asset/img/basic-concepts-overview/components.jpg)
****
初始化有兩種配置方式，本人採用第二種
### 配置1: data 和 option 交織在一起
用起來較直觀，但資料常變動時會比較麻煩
![配置1](https://echarts.apache.org/v4/zh/documents/asset/img/basic-concepts-overview/series-all-a.jpg)
****
### 配置2: 把 data 抽出來集中管理，在 series 中只設定對應的維度
較不直觀，但對於頻繁更動資料的情況較方便
![配置2](https://echarts.apache.org/v4/zh/documents/asset/img/basic-concepts-overview/series-all-b.jpg)


實作時把圖表製成 component 資料從外部傳到元件內
![方法比較](https://i.imgur.com/IH4xgjy.jpg)

- **把各種 chart 類型製成 component**  
  優點是單支 component 複雜度低 缺點是耦合度高，適合圖表類型不多或圖表內容差異大的情況
- **只做一個 chart component，在資料傳入時帶上 chart 類型直接在元件中判斷產出哪種圖表**  
  優點是低耦合與外部的接口一致 缺點是元件內部變得較複雜，適合圖表類型較多且內容相似的情況
此專案目前的圖表種類差異較大，採用第一種方法程式碼比較好管理

## example🤏
以 dashboard 的 barchart 為例：  
![dashboard畫面](https://truth.bahamut.com.tw/s01/202101/6da2cb41566282e5d5ec744a49d181ab.JPG)  

### 1. 父元件(dashboard.vue)從 Vue store 拿所有資料(allData)
allData 都是從 API 撈回來未經處理過的數據
![allData](https://i.imgur.com/x8YRBIN.png)  

### 2. 用 computed 的方式處理 allData 並返回特定的數據
在父元件這一層處理資料然後再分發給對應的 chart component 去作呈現

dashboard 的 barchart 有資料篩選的功能
![data filter](https://i.imgur.com/GnXQOVz.png)

**以下為範例，並非實際的code**  
``` javascript
computed: {
 barchartDataset() {
  // 取用篩選器的條件，這邊以"資料類型"和"數值區間"為例(e.g. "觀看數" "0 ~ 1000" 的文章)
  // dataType: "view", dataRangeMin: 0, dataRangeMax: 1000
  const { dataType, dataRangeMin, dataRangeMax } = this.filterConfig;
  
  // 全部的資料，開始篩選處理
  let dataset = this.allData;
  
  // 遍歷 dataset 裡面的資料， 
  dataset = dataset.filter((article) => {
    // article 為單篇文章的數據(標題，發佈時間，觀看數，GP...)
    // 用 Lodash.inRange 來判斷文章的"觀看數"是否在區間內
    return _.inRange(item[dataType], dataRangeMin, dataRangeMax)
  });
  
  // 條件很多就如法炮製，層層處理(以下省略)
  
  // 篩選完後要回傳 chart component 可以直接用的格式，參考上面提過的 ECharts 的配置方式
  return [
    ['title', dataType],
    ...dataset.map((article) => [article.title, article.[dataType]])
  ]
  // 格式如下
  // [
  //   [ title: "觀看數" ],
  //   [ 文章1: 520 ],
  //   [ 文章2: 168 ]...
  // ]
  
 }
}

```
### 3. 把數據丟給 chart component 呈現

以下是 (bar)chart component 的程式碼
``` javascript
// 從父元件接到的資料
props: ['inputData'],
data() {
  return{
    // 圖表的option，參考上面提過的 ECharts 的配置方式
    options: {
      // 中間省略...
      // 資料
      dataset: {
        source: this.inputData,
      },
      // 設定圖表種類與資料對應維度
      series: [
        {
          type: 'bar',
          encode: {
            x: 0,
            y: 1,
          },
        },
      ],
    }
  }
},
// 因應篩選器會變動，所以監聽傳入的資料，變動圖表的基本設定(Y軸名稱，Y軸最大值...)
watch: {
  inputData(newData) {
    this.options.dataset.source = newData;
    const allData = newData.slice(1, -1);
    // 設定圖表Y軸名稱，以目前的例子就是 "觀看數"
    this.options.yAxis.name = newData[0][1]; 
    // 設定圖表Y軸最大值(固定 bar 的高度，不要動態調整)，找到最大的Y軸數據定為最大值
    this.options.yAxis.max = Math.max(...allData.map((article) => article[1]));
  }
}
```