移動端自適應
ECharts
工作在用戶指定高寬的 DOM 節點(容器)中。ECharts
的『組件』和『系列』都在這個 DOM 節點中,每個節點都可以由用戶指定位置。圖表庫內部並不適宜實現 DOM
文檔流佈局,因此採用類似絕對佈局的簡單容易理解的佈局方式。但是有時候容器尺寸極端時,這種方式並不能自動避免組件重疊的情況,尤其在移動端小屏的情況下。
另外,有時會出現一個圖表需要同時在PC、移動端上展現的場景。這需要 ECharts
內部組件隨着容器尺寸變化而變化的能力。
爲了解決這個問題,ECharts
完善了組件的定位設置,並且實現了類似 CSS Media Query
的自適應能力。
ECharts
組件的定位和佈局
大部分『組件』和『系列』會遵循兩種定位方式:
left/right/top/bottom/width/height
定位方式:
這六個量中,每個量都可以是『絕對值』或者『百分比』或者『位置描述』。
-
絕對值
單位是瀏覽器像素(px),用
number
形式書寫(不寫單位)。例如{left: 23, height: 400}
。 -
百分比
表示佔 DOM 容器高寬的百分之多少,用
string
形式書寫。例如{right: '30%', bottom: '40%'}
。 -
位置描述
-
可以設置
left: 'center'
,表示水平居中。 -
可以設置
top: 'middle'
,表示垂直居中。
這六個量的概念,和 CSS 中六個量的概念類似:
left
:距離 DOM 容器左邊界的距離。right
:距離 DOM 容器右邊界的距離。top
:距離 DOM 容器上邊界的距離。bottom
:距離 DOM 容器下邊界的距離。width
:寬度。height
:高度。
在橫向,left
、right
、width
三個量中,只需兩個量有值即可,因爲任兩個量可以決定組件的位置和大小,例如 left
和 right
或者 right
和 width
都可以決定組件的位置和大小。 縱向,top
、bottom
、height
三個量,和橫向類同不贅述。
center/radius
定位方式:
-
center
是一個數組,表示 [x, y],其中,x、y可以是『絕對值』或者『百分比』,含義和前述相同。
-
radius
是一個數組,表示 [內半徑, 外半徑],其中,內外半徑可以是『絕對值』或者『百分比』,含義和前述相同。
在自適應容器大小時,百分比設置是很有用的。
橫向(horizontal
)和縱向(vertical
)
ECharts
的『外觀狹長』型的組件(如 legend、visualMap、dataZoom、timeline
等),大多提供了『橫向佈局』『縱向佈局』的選擇。例如,在細長的移動端屏幕上,可能適合使用『縱向佈局』;在PC寬屏上,可能適合使用『橫向佈局』。
橫縱向佈局的設置,一般在『組件』或者『系列』的 orient
或者 layout
配置項上,設置爲 'horizontal'
或者 'vertical'
。
於 ECharts2 的兼容:
ECharts2
中的 x/x2/y/y2
的命名方式仍被兼容,對應於 left/right/top/bottom
。但是建議寫 left/right/top/bottom
。
位置描述中,爲兼容 ECharts2
,可以支持一些看起來略奇怪的設置:left: 'right'、left: 'left'、top: 'bottom'、top: 'top'
。這些語句分別等效於:right: 0、left: 0、bottom: 0、top: 0
,寫成後者就不奇怪了。
Media Query
Media Query
提供了『隨着容器尺寸改變而改變』的能力。
如下例子,可嘗試拖動右下角的圓點,隨着尺寸變化,legend
和 系列會自動改變佈局位置和方式。
要在 option
中設置 Media Query
須遵循如下格式:
option = {
baseOption: { // 這裏是基本的『原子option』。
title: {...},
legend: {...},
series: [{...}, {...}, ...],
...
},
media: [ // 這裏定義了 media query 的逐條規則。
{
query: {...}, // 這裏寫規則。
option: { // 這裏寫此規則滿足下的option。
legend: {...},
...
}
},
{
query: {...}, // 第二個規則。
option: { // 第二個規則對應的option。
legend: {...},
...
}
},
{ // 這條裏沒有寫規則,表示『默認』,
option: { // 即所有規則都不滿足時,採納這個option。
legend: {...},
...
}
}
]
};
上面的例子中,baseOption
、以及 media
每個 option
都是『原子 option
』,即普通的含有各組件、系列定義的 option
。而由『原子option
』組合成的整個 option
,我們稱爲『複合 option
』。baseOption
是必然被使用的,此外,滿足了某個 query
條件時,對應的 option
會被使用 chart.mergeOption()
來 merge
進去。
query:
每個 query
類似於這樣:
{
minWidth: 200,
maxHeight: 300,
minAspectRatio: 1.3
}
現在支持三個屬性:width
、height
、aspectRatio
(長寬比)。每個屬性都可以加上 min
或 max
前綴。比如,minWidth: 200
表示『大於等於200px
寬度』。兩個屬性一起寫表示『並且』,比如:{minWidth: 200, maxHeight: 300}
表示『大於等於200px
寬度,並且小於等於300px高度』。
option:
media
中的 option
既然是『原子 option
』,理論上可以寫任何 option
的配置項。但是一般我們只寫跟佈局定位相關的,例如截取上面例子中的一部分 query option
:
media: [
...,
{
query: {
maxAspectRatio: 1 // 當長寬比小於1時。
},
option: {
legend: { // legend 放在底部中間。
right: 'center',
bottom: 0,
orient: 'horizontal' // legend 橫向佈局。
},
series: [ // 兩個餅圖左右佈局。
{
radius: [20, '50%'],
center: ['50%', '30%']
},
{
radius: [30, '50%'],
center: ['50%', '70%']
}
]
}
},
{
query: {
maxWidth: 500 // 當容器寬度小於 500 時。
},
option: {
legend: {
right: 10, // legend 放置在右側中間。
top: '15%',
orient: 'vertical' // 縱向佈局。
},
series: [ // 兩個餅圖上下佈局。
{
radius: [20, '50%'],
center: ['50%', '30%']
},
{
radius: [30, '50%'],
center: ['50%', '75%']
}
]
}
},
...
]
多個 query
被滿足時的優先級:
注意,可以有多個 query
同時被滿足,會都被 mergeOption
,定義在後的後被 merge
(即優先級更高)。
默認 query
:
如果 media
中有某項不寫 query
,則表示『默認值』,即所有規則都不滿足時,採納這個option
。
容器大小實時變化時的注意事項:
在不少情況下,並不需要容器DOM節點任意隨着拖拽變化大小,而是隻是根據不同終端設置幾個典型尺寸。
但是如果容器DOM節點需要能任意隨着拖拽變化大小,那麼目前使用時需要注意這件事:某個配置項,如果在某一個 query option
中出現,那麼在其他 query option
中也必須出現,否則不能夠迴歸到原來的狀態。(left/right/top/bottom/width/height
不受這個限制。)
『複合 option
』 中的 media
不支持 merge
也就是說,當第二(或三、四、五 …)次 chart.setOption(rawOption)
時,如果 rawOption
是 複合option
(即包含 media
列表),那麼新的 rawOption.media
列表不會和老的 media
列表進行 merge
,而是簡單替代。當然,rawOption.baseOption
仍然會正常和老的 option
進行merge
。
其實,很少有場景需要使用『複合 option
』來多次 setOption
,而我們推薦的做法是,使用 mediaQuery
時,第一次setOption
使用『複合 option
』,後面 setOption
時僅使用 『原子 option
』,也就是僅僅用 setOption
來改變 baseOption
。
最後看一個和時間軸結合的例子: