echarts實現(xiàn)響應式定位和布局
ECharts 圖表顯示在用戶指定高寬的 DOM 節(jié)點(容器)中。
有時候我們希望在 PC 和 移動設備上都能夠很好的展示圖表的內容,實現(xiàn)響應式的設計,為了解決這個問題,ECharts 完善了組件的定位設置,并且實現(xiàn)了類似 CSS Media Query 的自適應能力。
ECharts 組件的定位和布局
大部分『組件』和『系列』會遵循兩種定位方式。
1、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 三個量,和橫向類同不贅述。
2、center / radius 定位方式
center
是一個數(shù)組,表示 [x, y]
,其中,x
、y
可以是『絕對值』或者『百分比』,表示橫向和縱向。
radius
是一個數(shù)組,表示 [內半徑, 外半徑]
,其中,內外半徑可以是『絕對值』或者『百分比』,含義和前述相同。
在自適應容器大小時,百分比設置是很有用的。
3、橫向(horizontal)和縱向(vertical)
ECharts的『外觀狹長』型的組件(如 legend、visualMap、dataZoom、timeline等),大多提供了『橫向布局』『縱向布局』的選擇。例如,在細長的移動端屏幕上,可能適合使用『縱向布局』;在PC寬屏上,可能適合使用『橫向布局』。
橫縱向布局的設置,一般在『組件』或者『系列』的 orient 或者 layout 配置項上,設置為 'horizontal' 或者 'vertical'。
以下實例中我們可以可嘗試拖動右下角的圓點,圖表會隨著屏幕尺寸變化,legend 和 系列會自動改變布局位置和方式。
實例中我們使用了 jQuery 來加載外部數(shù)據(jù),使用時我們需要引入 jQuery 庫。
$.when( $.getScript('https://www.runoob.com/static/js/timelineGDP.js'), $.getScript('https://www.runoob.com/static/js/draggable.js') ).done(function () { draggable.init( $('div[_echarts_instance_]')[0], myChart, { width: 700, height: 400, throttle: 70 } ); myChart.hideLoading(); option = { baseOption: { title : { text: '南丁格爾玫瑰圖', subtext: '純屬虛構', x:'center' }, tooltip : { trigger: 'item', formatter: "{a} : {c} (vvxyksv9kd%)" }, legend: { data:['rose1','rose2','rose3','rose4','rose5','rose6','rose7','rose8'] }, toolbox: { show : true, feature : { mark : {show: true}, dataView : {show: true, readOnly: false}, magicType : { show: true, type: ['pie', 'funnel'] }, restore : {show: true}, saveAsImage : {show: true} } }, calculable : true, series : [ { name:'半徑模式', type:'pie', roseType : 'radius', label: { normal: { show: false }, emphasis: { show: true } }, lableLine: { normal: { show: false }, emphasis: { show: true } }, data:[ {value:10, name:'rose1'}, {value:5, name:'rose2'}, {value:15, name:'rose3'}, {value:25, name:'rose4'}, {value:20, name:'rose5'}, {value:35, name:'rose6'}, {value:30, name:'rose7'}, {value:40, name:'rose8'} ] }, { name:'面積模式', type:'pie', roseType : 'area', data:[ {value:10, name:'rose1'}, {value:5, name:'rose2'}, {value:15, name:'rose3'}, {value:25, name:'rose4'}, {value:20, name:'rose5'}, {value:35, name:'rose6'}, {value:30, name:'rose7'}, {value:40, name:'rose8'} ] } ] }, media: [ { option: { legend: { right: 'center', bottom: 0, orient: 'horizontal' }, series: [ { radius: [20, '50%'], center: ['25%', '50%'] }, { radius: [30, '50%'], center: ['75%', '50%'] } ] } }, { query: { minAspectRatio: 1 }, option: { legend: { right: 'center', bottom: 0, orient: 'horizontal' }, series: [ { radius: [20, '50%'], center: ['25%', '50%'] }, { radius: [30, '50%'], center: ['75%', '50%'] } ] } }, { query: { maxAspectRatio: 1 }, option: { legend: { right: 'center', bottom: 0, orient: 'horizontal' }, series: [ { radius: [20, '50%'], center: ['50%', '30%'] }, { radius: [30, '50%'], center: ['50%', '70%'] } ] } }, { query: { maxWidth: 500 }, option: { legend: { right: 10, top: '15%', orient: 'vertical' }, series: [ { radius: [20, '50%'], center: ['50%', '30%'] }, { radius: [30, '50%'], center: ['50%', '75%'] } ] } } ] }; myChart.setOption(option); });
要在 option 中設置 Media Query 須遵循如下格式:
option = { baseOption: { // 這里是基本的『原子option』。 title: {...}, legend: {...}, series: [{...}, {...}, ...], ... }, media: [ // 這里定義了 media query 的逐條規(guī)則。 { query: {...}, // 這里寫規(guī)則。 option: { // 這里寫此規(guī)則滿足下的option。 legend: {...}, ... } }, { query: {...}, // 第二個規(guī)則。 option: { // 第二個規(guī)則對應的option。 legend: {...}, ... } }, { // 這條里沒有寫規(guī)則,表示『默認』, option: { // 即所有規(guī)則都不滿足時,采納這個option。 legend: {...}, ... } } ] };
上面的例子中,baseOption、以及 media 每個 option 都是『原子 option』,即普通的含有各組件、系列定義的 option。而由『原子option』組合成的整個 option,我們稱為『復合 option』。baseOption 是必然被使用的,此外,滿足了某個 query 條件時,對應的 option 會被使用 chart.mergeOption() 來 merge 進去。
4、query
每個 query 類似于這樣:
{ minWidth: 200, maxHeight: 300, minAspectRatio: 1.3 }
現(xiàn)在支持三個屬性:width、height、aspectRatio(長寬比)。每個屬性都可以加上 min 或 max 前綴。比如,minWidth: 200 表示『大于等于200px寬度』。兩個屬性一起寫表示『并且』,比如:{minWidth: 200, maxHeight: 300} 表示『大于等于200px寬度,并且小于等于300px高度』。
5、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%'] } ] } }, ... ]
6、多個 query 被滿足時的優(yōu)先級
注意,可以有多個 query 同時被滿足,會都被 mergeOption,定義在后的后被 merge(即優(yōu)先級更高)。
7、默認 query
如果 media 中有某項不寫 query,則表示『默認值』,即所有規(guī)則都不滿足時,采納這個option。
8、容器大小實時變化時的注意事項
在不少情況下,并不需要容器DOM節(jié)點任意隨著拖拽變化大小,而是只是根據(jù)不同終端設置幾個典型尺寸。
但是如果容器DOM節(jié)點需要能任意隨著拖拽變化大小,那么目前使用時需要注意這件事:某個配置項,如果在某一個 query option 中出現(xiàn),那么在其他 query option 中也必須出現(xiàn),否則不能夠回歸到原來的狀態(tài)。(left/right/top/bottom/width/height 不受這個限制。)
9、『復合 option』 中的 media 不支持 merge
也就是說,當?shù)诙ɑ蛉?、四、?...)次 chart.setOption(rawOption) 時,如果 rawOption 是 復合option(即包含 media 列表),那么新的 rawOption.media 列表不會和老的 media 列表進行 merge,而是簡單替代。當然,rawOption.baseOption 仍然會正常和老的 option 進行merge。 其實,很少有場景需要使用『復合 option』來多次 setOption,而我們推薦的做法是,使用 mediaQuery 時,第一次setOption使用『復合 option』,后面 setOption 時僅使用 『原子 option』,也就是僅僅用 setOption 來改變 baseOption。
以下中我們使用了 jQuery 來加載外部數(shù)據(jù),使用時我們需要引入 jQuery 庫。該實例是一個和時間軸結合的例子:
$.when( $.getScript('https://www.runoob.com/static/js/timelineGDP.js'), $.getScript('https://www.runoob.com/static/js/draggable.js') ).done(function () { draggable.init( $('div[_echarts_instance_]')[0], myChart, { width: 700, height: 630, lockY: true, throttle: 70 } ); myChart.hideLoading(); var categoryData = [ '北京','天津','河北','山西','內蒙古','遼寧','吉林','黑龍江', '上海','江蘇','浙江','安徽','福建','江西','山東','河南', '湖北','湖南','廣東','廣西','海南','重慶','四川','貴州', '云南','西藏','陜西','甘肅','青海','寧夏','新疆' ]; option = { baseOption: { timeline: { axisType: 'category', autoPlay: true, playInterval: 1000, data: [ '2002-01-01', '2003-01-01', '2004-01-01', '2005-01-01', '2006-01-01', '2007-01-01', '2008-01-01', '2009-01-01', '2010-01-01', '2011-01-01' ], label: { formatter : function(s) { return (new Date(s)).getFullYear(); } } }, title: { subtext: 'Media Query 示例' }, tooltip: { trigger:'axis', axisPointer: { type: 'shadow' } }, xAxis: { type: 'value', name: 'GDP(億元)', max: 30000, data: null }, yAxis: { type: 'category', data: categoryData, axisLabel: {interval: 0}, splitLine: {show: false} }, legend: { data: ['第一產(chǎn)業(yè)', '第二產(chǎn)業(yè)', '第三產(chǎn)業(yè)', 'GDP', '金融', '房地產(chǎn)'], selected: { 'GDP': false, '金融': false, '房地產(chǎn)': false } }, calculable : true, series: [ {name: 'GDP', type: 'bar'}, {name: '金融', type: 'bar'}, {name: '房地產(chǎn)', type: 'bar'}, {name: '第一產(chǎn)業(yè)', type: 'bar'}, {name: '第二產(chǎn)業(yè)', type: 'bar'}, {name: '第三產(chǎn)業(yè)', type: 'bar'}, {name: 'GDP占比', type: 'pie'} ] }, media: [ { option: { legend: { orient: 'horizontal', left: 'right', itemGap: 10 }, grid: { left: '10%', top: 80, right: 90, bottom: 100 }, xAxis: { nameLocation: 'end', nameGap: 10, splitNumber: 5, splitLine: { show: true } }, timeline: { orient: 'horizontal', inverse: false, left: '20%', right: '20%', bottom: 10, height: 40 }, series: [ {name: 'GDP占比', center: ['75%', '30%'], radius: '28%'} ] } }, { query: {maxWidth: 670, minWidth: 550}, option: { legend: { orient: 'horizontal', left: 200, itemGap: 5 }, grid: { left: '10%', top: 80, right: 90, bottom: 100 }, xAxis: { nameLocation: 'end', nameGap: 10, splitNumber: 5, splitLine: { show: true } }, timeline: { orient: 'horizontal', inverse: false, left: '20%', right: '20%', bottom: 10, height: 40 }, series: [ {name: 'GDP占比', center: ['75%', '30%'], radius: '28%'} ] } }, { query: {maxWidth: 550}, option: { legend: { orient: 'vertical', left: 'right', itemGap: 5 }, grid: { left: 55, top: '32%', right: 100, bottom: 50 }, xAxis: { nameLocation: 'middle', nameGap: 25, splitNumber: 3 }, timeline: { orient: 'vertical', inverse: true, right: 10, top: 150, bottom: 10, width: 55 }, series: [ {name: 'GDP占比', center: ['45%', '20%'], radius: '28%'} ] } } ], options: [ { title: {text: '2002全國宏觀經(jīng)濟指標'}, series: [ {data: dataMap.dataGDP['2002']}, {data: dataMap.dataFinancial['2002']}, {data: dataMap.dataEstate['2002']}, {data: dataMap.dataPI['2002']}, {data: dataMap.dataSI['2002']}, {data: dataMap.dataTI['2002']}, {data: [ {name: '第一產(chǎn)業(yè)', value: dataMap.dataPI['2002sum']}, {name: '第二產(chǎn)業(yè)', value: dataMap.dataSI['2002sum']}, {name: '第三產(chǎn)業(yè)', value: dataMap.dataTI['2002sum']} ]} ] }, { title : {text: '2003全國宏觀經(jīng)濟指標'}, series : [ {data: dataMap.dataGDP['2003']}, {data: dataMap.dataFinancial['2003']}, {data: dataMap.dataEstate['2003']}, {data: dataMap.dataPI['2003']}, {data: dataMap.dataSI['2003']}, {data: dataMap.dataTI['2003']}, {data: [ {name: '第一產(chǎn)業(yè)', value: dataMap.dataPI['2003sum']}, {name: '第二產(chǎn)業(yè)', value: dataMap.dataSI['2003sum']}, {name: '第三產(chǎn)業(yè)', value: dataMap.dataTI['2003sum']} ]} ] }, { title : {text: '2004全國宏觀經(jīng)濟指標'}, series : [ {data: dataMap.dataGDP['2004']}, {data: dataMap.dataFinancial['2004']}, {data: dataMap.dataEstate['2004']}, {data: dataMap.dataPI['2004']}, {data: dataMap.dataSI['2004']}, {data: dataMap.dataTI['2004']}, {data: [ {name: '第一產(chǎn)業(yè)', value: dataMap.dataPI['2004sum']}, {name: '第二產(chǎn)業(yè)', value: dataMap.dataSI['2004sum']}, {name: '第三產(chǎn)業(yè)', value: dataMap.dataTI['2004sum']} ]} ] }, { title : {text: '2005全國宏觀經(jīng)濟指標'}, series : [ {data: dataMap.dataGDP['2005']}, {data: dataMap.dataFinancial['2005']}, {data: dataMap.dataEstate['2005']}, {data: dataMap.dataPI['2005']}, {data: dataMap.dataSI['2005']}, {data: dataMap.dataTI['2005']}, {data: [ {name: '第一產(chǎn)業(yè)', value: dataMap.dataPI['2005sum']}, {name: '第二產(chǎn)業(yè)', value: dataMap.dataSI['2005sum']}, {name: '第三產(chǎn)業(yè)', value: dataMap.dataTI['2005sum']} ]} ] }, { title : {text: '2006全國宏觀經(jīng)濟指標'}, series : [ {data: dataMap.dataGDP['2006']}, {data: dataMap.dataFinancial['2006']}, {data: dataMap.dataEstate['2006']}, {data: dataMap.dataPI['2006']}, {data: dataMap.dataSI['2006']}, {data: dataMap.dataTI['2006']}, {data: [ {name: '第一產(chǎn)業(yè)', value: dataMap.dataPI['2006sum']}, {name: '第二產(chǎn)業(yè)', value: dataMap.dataSI['2006sum']}, {name: '第三產(chǎn)業(yè)', value: dataMap.dataTI['2006sum']} ]} ] }, { title : {text: '2007全國宏觀經(jīng)濟指標'}, series : [ {data: dataMap.dataGDP['2007']}, {data: dataMap.dataFinancial['2007']}, {data: dataMap.dataEstate['2007']}, {data: dataMap.dataPI['2007']}, {data: dataMap.dataSI['2007']}, {data: dataMap.dataTI['2007']}, {data: [ {name: '第一產(chǎn)業(yè)', value: dataMap.dataPI['2007sum']}, {name: '第二產(chǎn)業(yè)', value: dataMap.dataSI['2007sum']}, {name: '第三產(chǎn)業(yè)', value: dataMap.dataTI['2007sum']} ]} ] }, { title : {text: '2008全國宏觀經(jīng)濟指標'}, series : [ {data: dataMap.dataGDP['2008']}, {data: dataMap.dataFinancial['2008']}, {data: dataMap.dataEstate['2008']}, {data: dataMap.dataPI['2008']}, {data: dataMap.dataSI['2008']}, {data: dataMap.dataTI['2008']}, {data: [ {name: '第一產(chǎn)業(yè)', value: dataMap.dataPI['2008sum']}, {name: '第二產(chǎn)業(yè)', value: dataMap.dataSI['2008sum']}, {name: '第三產(chǎn)業(yè)', value: dataMap.dataTI['2008sum']} ]} ] }, { title : {text: '2009全國宏觀經(jīng)濟指標'}, series : [ {data: dataMap.dataGDP['2009']}, {data: dataMap.dataFinancial['2009']}, {data: dataMap.dataEstate['2009']}, {data: dataMap.dataPI['2009']}, {data: dataMap.dataSI['2009']}, {data: dataMap.dataTI['2009']}, {data: [ {name: '第一產(chǎn)業(yè)', value: dataMap.dataPI['2009sum']}, {name: '第二產(chǎn)業(yè)', value: dataMap.dataSI['2009sum']}, {name: '第三產(chǎn)業(yè)', value: dataMap.dataTI['2009sum']} ]} ] }, { title : {text: '2010全國宏觀經(jīng)濟指標'}, series : [ {data: dataMap.dataGDP['2010']}, {data: dataMap.dataFinancial['2010']}, {data: dataMap.dataEstate['2010']}, {data: dataMap.dataPI['2010']}, {data: dataMap.dataSI['2010']}, {data: dataMap.dataTI['2010']}, {data: [ {name: '第一產(chǎn)業(yè)', value: dataMap.dataPI['2010sum']}, {name: '第二產(chǎn)業(yè)', value: dataMap.dataSI['2010sum']}, {name: '第三產(chǎn)業(yè)', value: dataMap.dataTI['2010sum']} ]} ] }, { title : {text: '2011全國宏觀經(jīng)濟指標'}, series : [ {data: dataMap.dataGDP['2011']}, {data: dataMap.dataFinancial['2011']}, {data: dataMap.dataEstate['2011']}, {data: dataMap.dataPI['2011']}, {data: dataMap.dataSI['2011']}, {data: dataMap.dataTI['2011']}, {data: [ {name: '第一產(chǎn)業(yè)', value: dataMap.dataPI['2011sum']}, {name: '第二產(chǎn)業(yè)', value: dataMap.dataSI['2011sum']}, {name: '第三產(chǎn)業(yè)', value: dataMap.dataTI['2011sum']} ]} ] } ] }; myChart.setOption(option); });
到此這篇關于echarts響應式定位和布局的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
利用純js + transition動畫實現(xiàn)移動端web輪播圖詳解
這篇文章主要給大家介紹了利用純js + transition動畫實現(xiàn)移動端web輪播圖的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考借鑒,下面來一起看看吧。2017-09-09(JS實現(xiàn))MapBar中坐標的加密和解密的腳本
(JS實現(xiàn))MapBar中坐標的加密和解密的腳本...2007-05-05