Published
- 37 min read
E-Charts 研究
E-Charts 研究
- 教學文件 連結
- 每個 Echart 中都可以建立多個圖表和坐標系
1. 系列 ( Series ):
- 代表: 一組數組及他們所對應的圖表,也可理解為一系列的數據
- 須包含: 一組數值、圖表型別 ( series type ),以及這些數據如何對應成圖的參數
- 圖表型別 ( series type ):
- 折線圖 ( line )
- 柱狀圖 ( bar )
- 餅圖 ( pie )
- 散點圖 ( scatter )
- 關係圖 ( graph )
- 樹圖 ( tree )
- 圖表型別 ( series type ):
除了將系列數據分別在 series 內部放置外,也可以全都放在 dataset 中,再系列 series 中以 encode 指定各個圖表需對應的數組位置
2.元件 ( component ):
- 除了 series ( 系列外 ) echarts 還有其他的各種設定,這邊統稱為元件
- echarts 中常見的元件如下:
- xAxis ( 直角坐標 x 軸 )
- yAxis ( 直角坐標 y 軸 )
- grid ( 直角坐標底板 )
- angleAxis ( 極坐標系角度軸 )
- radiusAxis ( 極坐標系半徑軸 )
- polar ( 極坐標系底板 )
- geo ( 地理坐標系 )
- dataZoom ( 數據縮放元件 )
- visualMap ( 視覺對應元件 )
- tooltip ( 提示框元件 )
- toolbar ( 工具欄元件 )
- lengend component ( 數據圖示元件 )
3. 用 option 描述圖表
- 功能: 使用者使用 option 來描述各種對圖表的各種需求
// 建立 echarts 實體。
var dom = document.getElementById('dom-id');
var chart = echarts.init(dom);
// 用 option 描述 `數據`、`數據如何對映成圖形`、`互動行為` 等。
// option 是個大的 JavaScript 對象。
var option = {
// option 每個屬性是一類元件。
legend: {...},
grid: {...},
tooltip: {...},
toolbox: {...},
dataZoom: {...},
visualMap: {...},
// 如果有多個同類元件,那麼就是個陣列。例如這裡有三個 X 軸。
xAxis: [
// 陣列每項表示一個元件實體,用 type 描述「子型別」。
{type: 'category', ...},
{type: 'category', ...},
{type: 'value', ...}
],
yAxis: [{...}, {...}],
// 這裡有多個系列,也是構成一個陣列。
series: [
// 每個系列,也有 type 描述「子型別」,即「圖表型別」。
{type: 'line', data: [['AA', 332], ['CC', 124], ['FF', 412], ... ]},
{type: 'line', data: [2231, 1234, 552, ... ]},
{type: 'line', data: [[4, 51], [8, 12], ... ]}
}]
};
// 呼叫 setOption 將 option 輸入 echarts,然後 echarts 渲染圖表。
chart.setOption(option);
相關資料 data 也可以放在 series 外,以 dataset 放置,並在 series 中 以 encode 只是需要對應哪個維度的數據 ( 注意: 此方法就可以不用在 xAxis 或 yAxis 中標示數據,但若需要標示 type ( category 或 value ) 則可放在 xAxis 或 yAxis 位置 )
var option = {
dataset: {
source: [
[121, 'XX', 442, 43.11],
[663, 'ZZ', 311, 91.14],
[913, 'ZZ', 312, 92.12],
...
]
},
xAxis: {},
yAxis: {},
series: [
// 數據從 dataset 中取,encode 中的數值是 dataset.source 的維度 index
// 維度是列,而這邊 encode 的數值是行 以 index 作為指派
{type: 'bar', encode: {x: 1, y: 0}},
{type: 'bar', encode: {x: 1, y: 2}},
{type: 'scatter', encode: {x: 1, y: 3}},
...
]
};
4. 元件的定位
- 定位方式與 CSS 中的絕對定位雷同,主要以 top / right / down / left /width / height 進行絕對定位,其位置是基於 exharts 綁定的 Dom 節點
- 其設定方式
- 以數值不加單位 ex: left 54 就等於 54 px
- 以字串加 % ex: right: 20%
- 以下範例,是在 grid 元件 ( 直角坐標系的底板 ) 進行設定
- 其設定方式
- 從上圖,可以區分為兩個類型 橫向與縱向,而只要橫向與縱向各設定一種,基本上圖形就能自動算出
- 橫向: left, right, width
- 縱向: top, bottom, height
5. 坐標系
-
在大部分的系列上都需要以座標來標示位置 ex: line ( 折線圖 )、bar ( 柱狀圖 )、scatter ( 散點圖 )、 heatmap ( 熱力圖 ) …etc. 除了 pie ( 餅圖 )、tree ( 樹圖 ) 等等可以不用座標而獨立存在,而 graph ( 關係圖 ) 則既可獨立存在也可布局在座標中
-
scatter ( 散點體系 ): echart 自動關聯 data 內的陣列資料,以 data 中陣列的第一個數值為 x 另一個為 y 在 grid 上呈現
- 在直角坐標系中,當有多個 y 軸要對應時,可以在 series 中 以 yAxisIndex 指派 y 軸內對應資料 ( 同理 反之也可使用 xAxisIndex 指定 x 軸資料 )
- 當同一個 option 中 ( echart 實體 ) 有多張圖,可用 grid 分開
- grid 中有兩張圖,標註顯示位置
- xAxis 中使用 gridIndex 用以標示 此 x 軸對應 grid 中的哪張圖 ( yAxis 同理 )
- series 則使用 xAxisIndex 與 xAxis 對應
6. ECharts 中的樣式設置
- 種類分為
- 顏色主題 ( Theme )
- 調色盤
- 直接樣式設定 ( itemStyle、lineStyle、areaStyle、label… )
- 視覺對應 ( visualMap )
1. 顏色主題 ( Theme )
- 從 Echart 4 開始,除了預設主題外,還有兩套主題,分為為 ‘light’ 與 ‘dark’
// light 主題
var chart = echarts.init(dom, 'light');
// dark 主題
var chart = echarts.init(dom, 'dark');
- 若以上主題皆不喜歡,可以到 主題編輯器 自行定義主題,存為 JSON ,需要時再行載入
// 假設主題名稱是 "vintage"
// 這是 jQuery 的寫法
$.getJSON('xxx/xxx/vintage.json', function (themeJSON) {
echarts.registerTheme('vintage', JSON.parse(themeJSON))
var chart = echarts.init(dom, 'vintage');
});
2. 調色盤
- 可在 option 中設定全域或各 series 自己的調色盤
option = {
// 全域性調色盤。
color: ['#c23531','#2f4554', '#61a0a8', '#d48265', '#91c7ae','#749f83', '#ca8622', '#bda29a','#6e7074', '#546570', '#c4ccd3'],
series: [{
type: 'bar',
// 此係列自己的調色盤。
color: ['#dd6b66','#759aa0','#e69d87','#8dc1a9','#ea7e53','#eedd78','#73a373','#73b9bc','#7289ab', '#91ca8c','#f49f42'],
...
}, {
type: 'pie',
// 此係列自己的調色盤。
color: ['#37A2DA', '#32C5E9', '#67E0E3', '#9FE6B8', '#FFDB5C','#ff9f7f', '#fb7293', '#E062AE', '#E690D1', '#e7bcf3', '#9d96f5', '#8378EA', '#96BFFF'],
...
}]
}
3. 直接的樣式設定 itemStyle, lineStyle, areaStyle, label, …
- 是較常用的方式,在 option 中多處可設定 itemStyle, lineStyle, areaStyle, label…這些的地方可以直接設定圖形元素的顏色、線寬、點的大小、標籤的文字、標籤的樣式等等。
4. 高亮的樣式:emphasis
- 在滑鼠 hover 在元素上方時的高亮樣式表現,預設情況下,高亮是自普通樣式產生的,但是可以自行定義
option = {
series: {
type: 'scatter',
// 普通樣式。
itemStyle: {
// 點的顏色。
color: 'red'
},
label: {
show: true,
// 標籤的文字。
formatter: 'This is a normal label.'
},
// 高亮樣式。
emphasis: {
itemStyle: {
// 高亮時點的顏色。
color: 'blue'
},
label: {
show: true,
// 高亮時標籤的文字。
formatter: 'This is a emphasis label.'
}
}
}
}
註: Echarts 4 之前的寫法與這不同
7. loading 動畫
- ECharts 預設有提供了一個簡單的載入動畫。只需要呼叫 showLoading 方法顯示。數據載入完成後再呼叫 hideLoading 方法隱藏載入動畫。
// 此為 jQuery 的寫法
myChart.showLoading();
$.get('data.json').done(function (data) {
myChart.hideLoading();
myChart.setOption(...);
});
模擬非同步的完整程式碼
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ECharts</title>
<!-- 引入 echarts.js -->
<script src="https://cdn.staticfile.org/echarts/5.1.2/echarts.min.js"></script>
</head>
<body>
<!-- 為ECharts準備一個具備大小(寬高)的Dom -->
<div id="main" style="width: 600px;height:400px;"></div>
<script type="text/javascript">
// 基於準備好的dom,初始化echarts實體
var myChart = echarts.init(document.getElementById('main'));
var option;
function fetchData(cb) {
// 通過 setTimeout 模擬非同步載入
setTimeout(function () {
cb({
categories: ["襯衫","羊毛衫","雪紡衫","褲子","高跟鞋","襪子"],
data: [5, 20, 36, 10, 10, 20]
});
}, 3000);
}
// 初始 option
option = {
title: {
text: '非同步數據載入示例'
},
tooltip: {},
legend: {
data:['銷量']
},
xAxis: {
data: []
},
yAxis: {},
series: [{
name: '銷量',
type: 'bar',
data: []
}]
};
myChart.showLoading(); // showLoading
fetchData(function (data) {
myChart.hideLoading(); // hideLoading
myChart.setOption({
xAxis: {
data: data.categories
},
series: [{
// 根據名字對應到相應的系列
name: '銷量',
data: data.data
}]
});
});
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
</script>
</body>
</html>
- 及時更新的 echarts 寫法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ECharts</title>
<!-- 引入 echarts.js -->
<script src="https://cdn.staticfile.org/echarts/5.1.2/echarts.min.js"></script>
</head>
<body>
<!-- 為ECharts準備一個具備大小(寬高)的Dom -->
<div id="main" style="width: 600px;height:400px;"></div>
<script type="text/javascript">
// 基於準備好的dom,初始化echarts實體
var myChart = echarts.init(document.getElementById('main'));
var option;
var base = +new Date(2014, 9, 3);
var oneDay = 24 * 3600 * 1000;
var date = [];
var data = [Math.random() * 150];
var now = new Date(base);
function addData(shift) { // 將新資料加入
now = [now.getFullYear(), now.getMonth() + 1, now.getDate()].join('/');
date.push(now);
data.push((Math.random() - 0.4) * 10 + data[data.length - 1]);
if (shift) {
date.shift(); // 去掉最舊的一筆資料
data.shift();
}
now = new Date(+new Date(now) + oneDay);
}
for (var i = 1; i < 100; i++) {
addData();
}
option = {
xAxis: {
type: 'category',
boundaryGap: false,
data: date
},
yAxis: {
boundaryGap: [0, '50%'],
type: 'value'
},
series: [
{
name:'成交',
type:'line',
smooth:true,
symbol: 'none',
stack: 'a',
areaStyle: {
normal: {}
},
data: data
}
]
};
setInterval(function () {
addData(true);
myChart.setOption({ // 取到資料後設置 setOption
xAxis: {
data: date
},
series: [{
name:'成交',
data: data
}]
});
}, 500);
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
</script>
</body>
</html>
8. 使用 dataset 管理全部數據
- 從 Echart 4 開始支援將 所有的數據集集中一處好方便管理以及提高元件的複用性 ( 在 EChart 4 之前數據只能放在各個系列 series 中 )
- 原本 數據放在 series 中的寫法
option = {
xAxis: {
type: 'category',
data: ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie']
},
yAxis: {},
series: [
{
type: 'bar',
name: '2015',
data: [89.3, 92.1, 94.4, 85.4]
},
{
type: 'bar',
name: '2016',
data: [95.8, 89.4, 91.2, 76.9]
},
{
type: 'bar',
name: '2017',
data: [97.7, 83.1, 92.5, 78.1]
}
]
}
- 優點
- 直觀易理解
- 缺點
- 不利元件重複使用
- 而 Echart4 的數據集功能則可以解決上述缺點外,亦增加了以下優點
- 可指定數據對應到的圖表內容
- 配置與數據分開,較易於管理
- 支援更多的數據格式 ex: 二維陣列、對象陣列
8.1. 基礎範例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ECharts</title>
<!-- 引入 echarts.js -->
<script src="https://cdn.staticfile.org/echarts/5.1.2/echarts.min.js"></script>
</head>
<body>
<!-- 為ECharts準備一個具備大小(寬高)的Dom -->
<div id="main" style="width: 600px;height:400px;"></div>
<script type="text/javascript">
// 基於準備好的dom,初始化echarts實體
var myChart = echarts.init(document.getElementById('main'));
var option;
option = {
legend: {},
tooltip: {},
// 'column': 預設值。系列被安放到 dataset 的行上面。
// row': 系列被安放到 dataset 的列上面。
dataset: {
source: [
['product', '2015', '2016', '2017'],
['Matcha Latte', 43.3, 85.8, 93.7],
['Milk Tea', 83.1, 73.4, 55.1],
['Cheese Cocoa', 86.4, 65.2, 82.5],
['Walnut Brownie', 72.4, 53.9, 39.1]
]
},
// // 聲明一個 X 軸,類目軸(category)。預設情況下,類目軸對應到 dataset 第一行。
xAxis: {type: 'category'},
yAxis: {},
// Declare several bar series, each will be mapped
// to a column of dataset.source by default.
// 定義幾個數據系列,每一個都會被預設對映至相應的行
series: [
{type: 'bar'},
{type: 'bar'},
{type: 'bar'}
]
};
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
</script>
</body>
</html>
8.2. 數據對應到圖形
- 指定 dataset 的行 ( column ) 列 ( row ) 對應為圖形系列 ( series ),可以使用 series.seriesLayoutBy 來指定,預設是照 行 ( column ) 來對應
- 指定對照的數據組,可以使用 series.encode 屬性去指定對應到的 x、y 軸或是使用 visualMap 元件來對應顏色大小等視覺元素
- 注意這裡的 seriesLayoutBy 是指定 維度 ( dimentsion ),也就是一組數據項 ( item ) 中有多少的維度 ( dimentsion)
-
其預設值 為 column,也就是以 行 ( column ) 作為 每個數據項 ( row/item ) 內含的 數據類別 ( column / dimension )
ex: 以下範例的圖表二,就是 每組數據 ( row/item ) 有 4個 類別 ( coulmn / dimension )
-
反之若設置是 seriesLayoutBy: row ,也就是以 列 ( row ),作為每個數據項 ( column / item ) 內含的類別 ( row / dimentsion )
ex: 以下範例的圖表一,就是 每組數據 ( column/item ) 有 3個 類別 ( row / dimension )
-
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ECharts</title>
<!-- 引入 echarts.js -->
<script src="https://cdn.staticfile.org/echarts/5.1.2/echarts.min.js"></script>
</head>
<body>
<!-- 為ECharts準備一個具備大小(寬高)的Dom -->
<div id="main" style="width: 800px; height:600px;"></div>
<script type="text/javascript">
// 基於準備好的dom,初始化echarts實體
var myChart = echarts.init(document.getElementById('main'));
var option;
option = {
legend: {},
tooltip: {},
dataset: {
// 由於 seriesLayoutBy: column 是預設值,所以這裡總共有 4 個維度 3筆資料 ( item )
// 由於有 3 筆資料,因此 x 或 y 軸設定 category 則一致都會顯示 product 名
// 也就是說預設的做法是將各個數據項 item 的類別寫在 array 的第一項
// 第一列 (row) 的則是放 每個維度 數據所代表的 類別
source: [
// [ '', dimension, dimension, dimension , dimension ]
['product', '2012', '2013', '2014', '2015'],
['Matcha Latte', 41.1, 30.4, 65.1, 53.3], // item
['Milk Tea', 86.5, 92.1, 85.7, 83.1], // item
['Cheese Cocoa', 24.1, 67.2, 79.5, 86.4] // item
]
},
xAxis: [
//
{type: 'category', gridIndex: 0},
{type: 'category', gridIndex: 1}
],
yAxis: [
{gridIndex: 0},
{gridIndex: 1}
],
grid: [
{bottom: '55%'},
{top: '55%'}
],
series: [
// 這幾個系列會在第一個直角座標系中,每個系列對應到 dataset 的每一列。預設是行
// 所以數據 seriesLayoutBy: row 對應是直向的 ( 這邊是4個 也就是以 2012, 2013... 排列)
// 也就是 不含標示的話, row 有3組 (3個維度),column 有4組 ( 有4組 數據項 )
// 第二張圖 seriesLayoutBy 預設是 column ( 橫向數據排列 )
// 也就是 不含標示的話, column 有4組 (4個維度),row 有3組 ( 有3組 數據項 )
// xAxis/yAxis 對應的 是 grindIndex 其預設是 0 為第一張圖
// 另外 xAxis/yAxis 預設 type 為 value
// xAxisIndex / yAxis 預設為 0
{type: 'bar', seriesLayoutBy: 'row'},
{type: 'bar', seriesLayoutBy: 'row'},
{type: 'bar', seriesLayoutBy: 'row'},
// 這幾個系列會在第二個直角座標系中,每個系列對應到 dataset 的每一行。
{type: 'bar', xAxisIndex: 1, yAxisIndex: 1},
{type: 'bar', xAxisIndex: 1, yAxisIndex: 1},
{type: 'bar', xAxisIndex: 1, yAxisIndex: 1},
{type: 'bar', xAxisIndex: 1, yAxisIndex: 1}
]
};
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
</script>
</body>
</html>
8.3 維度 ( dimension )
-
承上所述 seriesLayoutBy 是指定 維度 ( dimentsion ),也就是一組數據項 ( item ) 中有多少的維度 ( dimentsion)
- 因此常見預設 ( coulumn ) 情況是將維度名的放在 dataset 的 第一列 ( row )
- 反之亦然,若設置是 ( row ) 則須將維度名放在 dataset 的第一行 ( column )
至於 dataset 是否含有維度名, echarts 會自動判斷,但也可以手動設定
dataset.sourceHeader: true
也就是第一行 ( 或列 ) 預設為維度名dataset.sourceHeader: false
也就是第一行 ( 或列 ) 開始就是數據
-
維度也可以直接在 dataset 或是 series 中進行指定與設定
var option1 = {
dataset: {
dimensions: [
// 寫法1: 使用物件表示
{name: 'score'},
// 寫法2: 也可以簡寫為 string,表示維度名。
'amount',
// 在寫法1中,也可以在 type 中指定維度型別。
{name: 'product', type: 'ordinal'}
],
source: [...]
},
...
};
var option2 = {
dataset: {
source: [...]
},
series: {
type: 'line',
// 在系列中設定的 dimensions 會更優先採納。
dimensions: [
null, // 可以設定為 null 表示不想設定維度名
'amount',
{name: 'product', type: 'ordinal'}
]
},
...
};
- 在 diemension 中,可以設定 type 對應其數據類型
number
數值 此為預設ordinal
對於文字、類目型別要在數軸上使用,須設定 ‘ordinal’ 型別,雖然 Echarts 本身會預設自動判斷這個型別,但保險起見使用者也可以自行設定time
數據型別的時間戳float
浮點數,int
整數型別,雖是 echart會自動辨別,但若有手動設置,有助於整體優化提升
8.4 數據到圖形的對應 ( series.encode )
- 了解 維度 ( dimension ) 與 數據組 ( item ) 間的關係後,再來理解 encode 的用法會較好
- 如上所述,ecahrts 的 seriesLayoutBy 是 column 也就是會以列 ( row ) 為數組,且以第一列為此 dimension 的名稱,而 encode 對應的就是該維度 ( dimenson ) 要在 x 或 y軸 呈現的定義,如下
var option = {
dataset: {
source: [
['score', 'amount', 'product'],
[89.3, 58212, 'Matcha Latte'],
[57.1, 78254, 'Milk Tea'],
[74.4, 41032, 'Cheese Cocoa'],
[50.1, 12755, 'Cheese Brownie'],
[89.7, 20145, 'Matcha Cocoa'],
[68.1, 79146, 'Tea'],
[19.6, 91852, 'Orange Juice'],
[10.6, 101852, 'Lemon Juice'],
[32.7, 20112, 'Walnut Brownie']
]
},
xAxis: {},
yAxis: {type: 'category'},
series: [
// 由於預設是 seriesLayoutBy 是 column 也就是維度為 column 數組為 row
{
type: 'bar',
encode: {
// 將 "amount" 列對映到 X 軸。
x: 'amount',
// 將 "product" 列對映到 Y 軸。
y: 'product'
}
}
]
};
- encode 的詳細設置說明
// 在任何座標系和系列中,都支援:
encode: {
// 使用 「名為 product 的維度」 和 「名為 score 的維度」 的值 在 tooltip 中顯示
tooltip: ['product', 'score']
// 使用 「維度 1」 和 「維度 3」 的維度名連起來作為系列名。(有時候名字比較長,這可以避免在 series.name 重複輸入這些名字)
seriesName: [1, 3],
// 表示使用 「維度2」 中的值作為 id。這在使用 setOption 動態更新數據時有用處,可以使新老數據用 id 對應起來,從而能夠產生合適的數據更新動畫。
itemId: 2,
// 指定數據項的名稱使用 「維度3」 在餅圖等圖表中有用,可以使這個名字顯示在圖例(legend)中。
itemName: 3
}
- 直角坐標軸 ( grid/cattesian )
// 直角座標系(grid/cartesian)特有的屬性:
encode: {
// 代表 「維度1」、「維度5」、「名為 score 的維度」 等3個維度對映到 X 軸:
x: [1, 5, 'score'],
// 把「維度0」對映到 Y 軸。
y: 0
}
- 單軸
// 單軸(singleAxis)特有的屬性:
encode: {
single: 3
}
- 於一些沒有座標系的圖表,例如餅圖、漏斗圖等,可以是:
// 對於一些沒有座標系的圖表,例如餅圖、漏斗圖等,可以是:
encode: {
value: 3
}
- 以下為結合以上較複雜的多圖範例
var sizeValue = '57%';
var symbolSize = 2.5;
option = {
legend: {},
tooltip: {},
toolbox: {
left: 'center',
feature: {
dataZoom: {}
}
},
grid: [
// 以 grid 設置位置,內部變數為 % 在上方已設置
{right: sizeValue, bottom: sizeValue},
{left: sizeValue, bottom: sizeValue},
{right: sizeValue, top: sizeValue},
{left: sizeValue, top: sizeValue}
],
xAxis: [
// 以 gridIndex 對應位置,可標示該軸名稱,也可指定該軸標籤樣式 ( 間格/是否旋轉 )
{type: 'value', gridIndex: 0, name: 'Income', axisLabel: {rotate: 50, interval: 0}},
{type: 'category', gridIndex: 1, name: 'Country', boundaryGap: false, axisLabel: {rotate: 50, interval: 0}},
{type: 'value', gridIndex: 2, name: 'Income', axisLabel: {rotate: 50, interval: 0}},
{type: 'value', gridIndex: 3, name: 'Life Expectancy', axisLabel: {rotate: 50, interval: 0}}
],
yAxis: [
{type: 'value', gridIndex: 0, name: 'Life Expectancy'},
{type: 'value', gridIndex: 1, name: 'Income'},
{type: 'value', gridIndex: 2, name: 'Population'},
{type: 'value', gridIndex: 3, name: 'Population'}
],
dataset: {
dimensions: [
'Income', // 每個維度的名稱定義
'Life Expectancy',
'Population',
'Country',
{name: 'Year', type: 'ordinal'} // 這邊也可簡寫為 'Year' 其意義不變
],
source: data // 注意: data 這組數組是從此變數中來的
},
series: [
{
type: 'scatter',
symbolSize: symbolSize,
xAxisIndex: 0,
yAxisIndex: 0,
encode: {
x: 'Income',
y: 'Life Expectancy',
// 需要在 tooltip 顯示的 維度
tooltip: [0, 1, 2, 3, 4]
}
},
{
type: 'scatter',
symbolSize: symbolSize,
xAxisIndex: 1,
yAxisIndex: 1,
encode: {
x: 'Country',
y: 'Income',
tooltip: [0, 1, 2, 3, 4]
}
},
{
type: 'scatter',
symbolSize: symbolSize,
xAxisIndex: 2,
yAxisIndex: 2,
encode: {
x: 'Income',
y: 'Population',
tooltip: [0, 1, 2, 3, 4]
}
},
{
type: 'scatter',
symbolSize: symbolSize,
xAxisIndex: 3,
yAxisIndex: 3,
encode: {
x: 'Life Expectancy',
y: 'Population',
tooltip: [0, 1, 2, 3, 4]
}
}
]
};
myChart.setOption(option);
});
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
https://i.imgur.com/Y0Yk18P.png[/img]
8.5 視覺通道(顏色、尺寸等)的對映
- 視覺通道 (
visualMap
) 是一張長條圖,以圖形顏色變換來對應不同數字大小間的顏色 ( 有設置 visualMap 也會在 不同值的 bar 上看到不同的顏色 )
option = {
dataset: {
source: [
['score', 'amount', 'product'],
[89.3, 58212, 'Matcha Latte'],
[57.1, 78254, 'Milk Tea'],
[74.4, 41032, 'Cheese Cocoa'],
[50.1, 12755, 'Cheese Brownie'],
[89.7, 20145, 'Matcha Cocoa'],
[68.1, 79146, 'Tea'],
[19.6, 91852, 'Orange Juice'],
[10.6, 101852, 'Lemon Juice'],
[32.7, 20112, 'Walnut Brownie']
]
},
grid: {containLabel: true},
xAxis: {name: 'amount'},
yAxis: {type: 'category'},
visualMap: {
orient: 'horizontal', // 呈現方向
left: 'center', // 示意圖位置
min: 10, // 數值區間
max: 100,
// 需要顯示高低標示
text: ['High Score', 'Low Score'],
// Map the score column to color
dimension: 0, // 對應的數值維度 ( 現在數據是 'score' 那欄 )
inRange: {
// 這些數值大小漸層色的設置
color: ['#65B581', '#FFCE34', '#FD665F']
}
},
series: [
{
type: 'bar',
encode: {
// Map the "amount" column to X axis.
x: 'amount',
// Map the "product" column to Y axis
y: 'product'
}
}
]
};
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
- 補充: 標籤的顯示 label.formatter,現在支援引用特定維度的值,例如:
- formatter 可以使用變數,對應的是該維度 ( dimesnion ) 裡的值
series: {
label: {
// `'{@score}'` 表示 「名為 score」 的維度里的值。
// `'{@[4]}'` 表示引用序號為 4 的維度里的值。
formatter: 'aaa{@product}bbb{@score}ccc{@[4]}ddd'
}
}
8.6 dataset 數據的各種格式
- 除了上述常用的二維陣列外,dataset 也支援如下面的 key-value 格式,但這類並不支援 seriesLayoutBy 參數
- 另外 dataset.source 也可以吃 JSON 格式 ( 若導出為 csv 可以使用如 dsv 或 PapaParse 轉 csv 成 JSON )
- 下方為 dataset 可接受的 key-value 類型
dataset: [{ // 第一種: 按行的 key-value 形式(對像陣列),這是個比較常見的格式 ( 陣列包物件 ) source: [ {product: 'Matcha Latte', count: 823, score: 95.8}, {product: 'Milk Tea', count: 235, score: 81.4}, {product: 'Cheese Cocoa', count: 1042, score: 91.2}, {product: 'Walnut Brownie', count: 988, score: 76.9} ] }, { // 第二種: 按列的 key-value 形式 (物件中包陣列) source: { 'product': ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie'], 'count': [823, 235, 1042, 988], 'score': [95.8, 81.4, 91.2, 76.9] } }]
8.7 series.data 與 dataset.source 的關係
- series 中的 data ( ECharts3 中就有的 ),其權重會高於在 series 外的 dataset,也就是若該 series 中有設定 data 則會以該 data 數據為主,而不是 daraset
{
xAxis: {
type: 'category'
data: ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie']
},
yAxis: {},
series: [{
type: 'bar',
name: '2015',
data: [89.3, 92.1, 94.4, 85.4]
}, {
type: 'bar',
name: '2016',
data: [95.8, 89.4, 91.2, 76.9]
}, {
type: 'bar',
name: '2017',
data: [97.7, 83.1, 92.5, 78.1]
}]
}
- Echarts 中有幾個情況不支援 dataset
- treenap、graph、lines 現在不支援 dataset,仍只能用 series.data
- 對於百萬筆以上的資料渲染,也不支援 dataset 需要使用 appendData 匯入資料
- 目前有支援 dataset 的圖表類型有: line、bar、pie 、scatter、 effectScatter、 parallel、 candlestick、 map、 funnel、 custom、多圖表
9. 使用transform進行數據轉換
- Echart5 開始加入的新功能,可以用 特定的轉換方法 ( transform ) 轉換原本的數據集( dataset )並產生一個新的數據集
- 常見的 轉換方法 ( transform ) ex: filter、sort、regression、boxplot、cluster、aggregate
- 此功能優點
- 可以將同分數據進行不同面向的展示
- 可針對圖表做運算處理並進行展示
- 進行數據排序
- 範例說明
- echarts 中 transform 的結果也是依托於 dataset 中,以 設定 dataset.transform 呈現
var option = { dataset: [{ // 這個 dataset 的 index 是 `0`。 source: [ ['Product', 'Sales', 'Price', 'Year'], ['Cake', 123, 32, 2011], ['Cereal', 231, 14, 2011], ['Tofu', 235, 5, 2011], ['Dumpling', 341, 25, 2011], ['Biscuit', 122, 29, 2011], ['Cake', 143, 30, 2012], ['Cereal', 201, 19, 2012], ['Tofu', 255, 7, 2012], ['Dumpling', 241, 27, 2012], ['Biscuit', 102, 34, 2012], ['Cake', 153, 28, 2013], ['Cereal', 181, 21, 2013], ['Tofu', 395, 4, 2013], ['Dumpling', 281, 31, 2013], ['Biscuit', 92, 39, 2013], ['Cake', 223, 29, 2014], ['Cereal', 211, 17, 2014], ['Tofu', 345, 3, 2014], ['Dumpling', 211, 35, 2014], ['Biscuit', 72, 24, 2014], ], // id: 'a' }, { // 這個 dataset 的 index 是 `1`。 // 這個 `transform` 配置,表示,此 dataset 的數據,來自於此 transform 的結果。 transform: { type: 'filter', config: { dimension: 'Year', value: 2011 } }, // 我們還可以設定這些可選的屬性: `fromDatasetIndex` 或 `fromDatasetId`。 // 這些屬性,指定了,transform 的輸入,來自於哪個 dataset。例如, // `fromDatasetIndex: 0` 表示輸入來自於 index 為 `0` 的 dataset 。又例如, // `fromDatasetId: 'a'` 表示輸入來自於 `id: 'a'` 的 dataset。 // 當這些屬性都不指定時,預設認為,輸入來自於 index 為 `0` 的 dataset 。 }, { // 這個 dataset 的 index 是 `2`。 // 同樣,這裡因為 `fromDatasetIndex` 和 `fromDatasetId` 都沒有被指定, // 那麼輸入預設來自於 index 為 `0` 的 dataset 。 transform: { // 這個型別為 "filter" 的 transform 能夠遍歷並篩選出滿足條件的數據項。 type: 'filter', // 每個 transform 如果需要有配置參數的話,都須配置在 `config` 里。 // 在這個 "filter" transform 中,`config` 用於指定篩選條件。 // 下面這個篩選條件是:選出維度( dimension )'Year' 中值為 2012 的所有 // 數據項。 config: { dimension: 'Year', value: 2012 } } }, { // 這個 dataset 的 index 是 `3`。 transform: { type: 'filter', config: { dimension: 'Year', value: 2013 } } }], series: [{ type: 'pie', radius: 50, center: ['25%', '50%'], // 這個餅圖系列,引用了 index 為 `1` 的 dataset 。也就是,引用了上述 // 2011 年那個 "filter" transform 的結果。 datasetIndex: 1 }, { type: 'pie', radius: 50, center: ['50%', '50%'], datasetIndex: 2 }, { type: 'pie', radius: 50, center: ['75%', '50%'], datasetIndex: 3 }] };
9.1 transform 的鏈式聲明
option = {
dataset: [{
source: [ ... ] // 原始數據
}, {
// 幾個 transform 被聲明成 array ,他們構成了一個鏈,
// 前一個 transform 的輸出是后一個 transform 的輸入。
// 簡單來看可以將整體視為一組轉換後的數據
// 下方範例是 將 原始數據 filter 後,再 sort
transform: [{
type: 'filter',
config: { dimension: 'Product', value: 'Tofu' }
}, {
type: 'sort',
config: { dimension: 'Year', order: 'desc' }
}]
}],
series: {
type: 'pie',
// 這個系列引用上述 transform 的結果。
datasetIndex: 1
}
}
9.2 利用一個 transform 輸出多個 data
- 多數情況下,transform 只需輸出一組 data,但也有少數狀況需要輸出多個 data
option = {
dataset: [{
// 這個 dataset 的 index 為 `0`。
source: [...] // 原始數據
}, {
// 這個 dataset 的 index 為 `1`。
transform: {
type: 'boxplot'
}
// 這個 "boxplot" transform 產生了兩個數據:
// result[0]: boxplot series 所需的數據。
// result[1]: 離群點數據。
// 當其他 series 或者 dataset 引用這個 dataset 時,他們預設只能得到
// result[0] 。
// 如果想要他們得到 result[1] ,需要額外聲明如下這樣一個 dataset :
}, {
// 這個 dataset 的 index 為 `2`。
// 這個額外的 dataset 指定了數據來源於 index 為 `1` 的 dataset。
fromDatasetIndex: 1,
// 並且指定了獲取 transform result[1] 。
fromTransformResult: 1
}],
xAxis: {
type: 'category'
},
yAxis: {
},
series: [{
name: 'boxplot',
type: 'boxplot',
// Reference the data from result[0].
// 這個 series 引用 index 為 `1` 的 dataset 。
datasetIndex: 1
}, {
name: 'outlier',
type: 'scatter',
// 這個 series 引用 index 為 `2` 的 dataset 。
// 從而也就得到了上述的 transform result[1] (即離群點數據)
datasetIndex: 2
}]
};
另外,dataset.fromTransformResult 和 dataset.transform 能同時出現在一個 dataset 中,這表示,這個 transform 的輸入,是上游的結果中以 fromTransformResult
獲取的結果。例如:
{
fromDatasetIndex: 1,
fromTransformResult: 1,
transform: {
type: 'sort',
config: { dimension: 2, order: 'desc' }
}
}
9.3 Print transform 在開發環境中的 debug 神器
- transform 可以設置 print ,其功能類似 console.log,方便 debug
option = {
dataset: [{
source: [ ... ]
}, {
transform: {
type: 'filter',
config: { ... }
// 配置為 `true` 后, transform 的結果
// 會被 console.log 列印出來。
print: true
}
}],
...
}
9.4 transform 中的 filter 用法
-
關於 transform type filter 中的 config 設定比較子的用法,其中小括號內的名稱是別名設定起來功能與比較子相同
>
( gt ) 可以用符號>
或是 文字 gt 表示為大於 ( 意為 greater than )>=
( gte ) ( 意為 greater than equal )<
( le ) ( 意為 lesser than )<=
( lte ) ( 意為 lesser than equal )=
( eq ) ( 意為 equal )!=
( ne、<> ) ( 意為 not equal )reg
-
其比較的條件是設於大括號中,若有多個條件則使用
,
分開ex: { dimension: 'Price', '>=': 20, '<': 30 }
-
比較的 data 可以是下面幾種
-
純數值
-
類數值字串 ( numeris string ) ex: ‘123’ ,其在轉換時會被換成數值進行比較,若有多餘的空格會被 trim() 掉
-
日期/時間 若需要比較 JS Date() 或是日期字串 ( ex: ‘2022-05-12’ ) 需要設定
parser:'time'
ex:
config: { dimension: 3, lt: '2012-05-12', parser: 'time' }
-
純字串,只能用
=
或是!=
其餘皆不能使用 -
reg 正規表示式篩選,比如
{ dimension: 'Name', reg: /\s+Müller\s*$/ }
能在'Name'
維度上選出姓'Müller'
的數據項
-
// 範例
option = {
dataset: [{
source: [
['Product', 'Sales', 'Price', 'Year'],
['Cake', 123, 32, 2011],
['Latte', 231, 14, 2011],
['Tofu', 235, 5, 2011],
['Milk Tee', 341, 25, 2011],
['Porridge', 122, 29, 2011],
['Cake', 143, 30, 2012],
['Latte', 201, 19, 2012],
['Tofu', 255, 7, 2012],
['Milk Tee', 241, 27, 2012],
['Porridge', 102, 34, 2012],
['Cake', 153, 28, 2013],
['Latte', 181, 21, 2013],
['Tofu', 395, 4, 2013],
['Milk Tee', 281, 31, 2013],
['Porridge', 92, 39, 2013],
['Cake', 223, 29, 2014],
['Latte', 211, 17, 2014],
['Tofu', 345, 3, 2014],
['Milk Tee', 211, 35, 2014],
['Porridge', 72, 24, 2014]
]
}, {
transform: {
type: 'filter',
// 除了 = 外 也苦已使用>=、<、!= 等等
// 也可以設定多個條件用 , 隔開 ex: { dimension: 'Price', '>=': 20, '<': 30 }
// 這裡的 dimension 的值除了可以用維度名外,也可以用 index ex: config: { dimension: 3, '=': 2011 }
// 比較除了數值外,也可以比較 類數值字串 ex: '123',其比較時會自動轉換成數值,並 trim 掉不必要的空格
// 如果要比較時間 ex: JS Date 或是 日期字串 ( '2022-05-12' )
config: { dimension: 'Year', '=': 2011 }
// 這個篩選條件表示,遍歷數據,篩選出維度( dimension )
// 'Year' 上值為 2011 的所有數據項。
}
}],
series: {
type: 'pie',
datasetIndex: 1 // 設定第一組數據
}
};
關於解析器 ( parser )
parser: 'time'
其會把原始值 ( JSDate()
或是時間字串'2023-05-22 03:11:22'
) 轉換成時間戳 timestamp 來做比較,若原始值式上述兩種外的型別則會被解析成NaN
parser: 'trim'
會將原始數值字串中的 空格、換行符號 去掉parser: 'number'
會將原始數據轉成數值,若不可轉則會被解析成 NaN 正常情況其預設就是數值不需要特別設定,但預設情況會較嚴格,無法解析字串如'30%'
、'12px'
這類的,此時就要手動設定成parser: 'number'
使其套用較寬鬆的轉換
以下是使用 parser 作為時間比較的範例
option = {
dataset: [{
source: [
['Product', 'Sales', 'Price', 'Date'],
['Milk Tee', 311, 21, '2012-05-12'],
['Cake', 135, 28, '2012-05-22'],
['Latte', 262, 36, '2012-06-02'],
['Milk Tee', 359, 21, '2012-06-22'],
['Cake', 121, 28, '2012-07-02'],
['Latte', 271, 36, '2012-06-22'],
...
]
}, {
transform: {
type: 'filter',
config: {
{ dimension: 'Date', '>=': '2012-05', '<': '2012-06', parser: 'time' }
}
}
}]
}
關於邏輯比較
- Echarts 可以支援 and/or/not ,也可以巢狀 ( 其中 and 與 or 因為有多個條件,所以後續接陣列
[ ]
, not 則後面接 物件{ }
)
option = {
dataset: [{
source: [...]
}, {
transform: {
type: 'filter',
config: {
// 使用 and 操作符。
// 類似地,同樣的位置也可以使用 「or」 或 「not」。
// 但是注意 「not」 后應該跟一個 {...} 而非 [...] 。
and: [
{ dimension: 'Year', '=': 2011 },
{ dimension: 'Price', '>=': 20, '<': 30 }
]
}
// 這個表達的是,選出 2011 年價格大於等於 20 但小於 30 的數據項。
}
}],
series: {
type: 'pie',
datasetIndex: 1
}
};
若是巢狀
transform: {
type: 'filter',
config: {
or: [{
and: [{
dimension: 'Price', '>=': 10, '<': 20
}, {
dimension: 'Sales', '<': 100
}, {
not: { dimension: 'Product', '=': 'Tofu' }
}]
}, {
and: [{
dimension: 'Price', '>=': 10, '<': 20
}, {
dimension: 'Sales', '<': 100
}, {
not: { dimension: 'Product', '=': 'Cake' }
}]
}]
}
}