当前位置:  首页>> 技术小册>> ECharts零基础入门

ECharts 图表显示在用户指定高宽的 DOM 节点(容器)中。

有时候我们希望在 PC 和 移动设备上都能够很好的展示图表的内容,实现响应式的设计,为了解决这个问题,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’。

实例
以下实例中我们可以可尝试拖动右下角的圆点,图表会随着屏幕尺寸变化,legend 和 系列会自动改变布局位置和方式。

实例中我们使用了 jQuery 来加载外部数据,使用时我们需要引入 jQuery 库。

实例

  1. $.when(
  2. $.getScript('https://www.maxiaoke.com/static/js/timelineGDP.js'),
  3. $.getScript('https://www.maxiaoke.com/static/js/draggable.js')
  4. ).done(function () {
  5. draggable.init(
  6. $('div[_echarts_instance_]')[0],
  7. myChart,
  8. {
  9. width: 700,
  10. height: 400,
  11. throttle: 70
  12. }
  13. );
  14. myChart.hideLoading();
  15. option = {
  16. baseOption: {
  17. title : {
  18. text: '南丁格尔玫瑰图',
  19. subtext: '纯属虚构',
  20. x:'center'
  21. },
  22. tooltip : {
  23. trigger: 'item',
  24. formatter: "{a} <br/>{b} : {c} ({d}%)"
  25. },
  26. legend: {
  27. data:['rose1','rose2','rose3','rose4','rose5','rose6','rose7','rose8']
  28. },
  29. toolbox: {
  30. show : true,
  31. feature : {
  32. mark : {show: true},
  33. dataView : {show: true, readOnly: false},
  34. magicType : {
  35. show: true,
  36. type: ['pie', 'funnel']
  37. },
  38. restore : {show: true},
  39. saveAsImage : {show: true}
  40. }
  41. },
  42. calculable : true,
  43. series : [
  44. {
  45. name:'半径模式',
  46. type:'pie',
  47. roseType : 'radius',
  48. label: {
  49. normal: {
  50. show: false
  51. },
  52. emphasis: {
  53. show: true
  54. }
  55. },
  56. lableLine: {
  57. normal: {
  58. show: false
  59. },
  60. emphasis: {
  61. show: true
  62. }
  63. },
  64. data:[
  65. {value:10, name:'rose1'},
  66. {value:5, name:'rose2'},
  67. {value:15, name:'rose3'},
  68. {value:25, name:'rose4'},
  69. {value:20, name:'rose5'},
  70. {value:35, name:'rose6'},
  71. {value:30, name:'rose7'},
  72. {value:40, name:'rose8'}
  73. ]
  74. },
  75. {
  76. name:'面积模式',
  77. type:'pie',
  78. roseType : 'area',
  79. data:[
  80. {value:10, name:'rose1'},
  81. {value:5, name:'rose2'},
  82. {value:15, name:'rose3'},
  83. {value:25, name:'rose4'},
  84. {value:20, name:'rose5'},
  85. {value:35, name:'rose6'},
  86. {value:30, name:'rose7'},
  87. {value:40, name:'rose8'}
  88. ]
  89. }
  90. ]
  91. },
  92. media: [
  93. {
  94. option: {
  95. legend: {
  96. right: 'center',
  97. bottom: 0,
  98. orient: 'horizontal'
  99. },
  100. series: [
  101. {
  102. radius: [20, '50%'],
  103. center: ['25%', '50%']
  104. },
  105. {
  106. radius: [30, '50%'],
  107. center: ['75%', '50%']
  108. }
  109. ]
  110. }
  111. },
  112. {
  113. query: {
  114. minAspectRatio: 1
  115. },
  116. option: {
  117. legend: {
  118. right: 'center',
  119. bottom: 0,
  120. orient: 'horizontal'
  121. },
  122. series: [
  123. {
  124. radius: [20, '50%'],
  125. center: ['25%', '50%']
  126. },
  127. {
  128. radius: [30, '50%'],
  129. center: ['75%', '50%']
  130. }
  131. ]
  132. }
  133. },
  134. {
  135. query: {
  136. maxAspectRatio: 1
  137. },
  138. option: {
  139. legend: {
  140. right: 'center',
  141. bottom: 0,
  142. orient: 'horizontal'
  143. },
  144. series: [
  145. {
  146. radius: [20, '50%'],
  147. center: ['50%', '30%']
  148. },
  149. {
  150. radius: [30, '50%'],
  151. center: ['50%', '70%']
  152. }
  153. ]
  154. }
  155. },
  156. {
  157. query: {
  158. maxWidth: 500
  159. },
  160. option: {
  161. legend: {
  162. right: 10,
  163. top: '15%',
  164. orient: 'vertical'
  165. },
  166. series: [
  167. {
  168. radius: [20, '50%'],
  169. center: ['50%', '30%']
  170. },
  171. {
  172. radius: [30, '50%'],
  173. center: ['50%', '75%']
  174. }
  175. ]
  176. }
  177. }
  178. ]
  179. };
  180. myChart.setOption(option);
  181. });

要在 option 中设置 Media Query 须遵循如下格式:

  1. option = {
  2. baseOption: { // 这里是基本的『原子option』。
  3. title: {...},
  4. legend: {...},
  5. series: [{...}, {...}, ...],
  6. ...
  7. },
  8. media: [ // 这里定义了 media query 的逐条规则。
  9. {
  10. query: {...}, // 这里写规则。
  11. option: { // 这里写此规则满足下的option。
  12. legend: {...},
  13. ...
  14. }
  15. },
  16. {
  17. query: {...}, // 第二个规则。
  18. option: { // 第二个规则对应的option。
  19. legend: {...},
  20. ...
  21. }
  22. },
  23. { // 这条里没有写规则,表示『默认』,
  24. option: { // 即所有规则都不满足时,采纳这个option。
  25. legend: {...},
  26. ...
  27. }
  28. }
  29. ]
  30. };

上面的例子中,baseOption、以及 media 每个 option 都是『原子 option』,即普通的含有各组件、系列定义的 option。而由『原子option』组合成的整个 option,我们称为『复合 option』。baseOption 是必然被使用的,此外,满足了某个 query 条件时,对应的 option 会被使用 chart.mergeOption() 来 merge 进去。

query
每个 query 类似于这样:

  1. {
  2. minWidth: 200,
  3. maxHeight: 300,
  4. minAspectRatio: 1.3
  5. }

现在支持三个属性:width、height、aspectRatio(长宽比)。每个属性都可以加上 min 或 max 前缀。比如,minWidth: 200 表示『大于等于200px宽度』。两个属性一起写表示『并且』,比如:{minWidth: 200, maxHeight: 300} 表示『大于等于200px宽度,并且小于等于300px高度』。

option
media中的 option 既然是『原子 option』,理论上可以写任何 option 的配置项。但是一般我们只写跟布局定位相关的,例如截取上面例子中的一部分 query option:

  1. media: [
  2. ...,
  3. {
  4. query: {
  5. maxAspectRatio: 1 // 当长宽比小于1时。
  6. },
  7. option: {
  8. legend: { // legend 放在底部中间。
  9. right: 'center',
  10. bottom: 0,
  11. orient: 'horizontal' // legend 横向布局。
  12. },
  13. series: [ // 两个饼图左右布局。
  14. {
  15. radius: [20, '50%'],
  16. center: ['50%', '30%']
  17. },
  18. {
  19. radius: [30, '50%'],
  20. center: ['50%', '70%']
  21. }
  22. ]
  23. }
  24. },
  25. {
  26. query: {
  27. maxWidth: 500 // 当容器宽度小于 500 时。
  28. },
  29. option: {
  30. legend: {
  31. right: 10, // legend 放置在右侧中间。
  32. top: '15%',
  33. orient: 'vertical' // 纵向布局。
  34. },
  35. series: [ // 两个饼图上下布局。
  36. {
  37. radius: [20, '50%'],
  38. center: ['50%', '30%']
  39. },
  40. {
  41. radius: [30, '50%'],
  42. center: ['50%', '75%']
  43. }
  44. ]
  45. }
  46. },
  47. ...
  48. ]

多个 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。
以下中我们使用了 jQuery 来加载外部数据,使用时我们需要引入 jQuery 库。该实例是一个和时间轴结合的例子:

实例

  1. $.when(
  2. $.getScript('https://www.maxiaoke.com/static/js/timelineGDP.js'),
  3. $.getScript('https://www.maxiaoke.com/static/js/draggable.js')
  4. ).done(function () {
  5. draggable.init(
  6. $('div[_echarts_instance_]')[0],
  7. myChart,
  8. {
  9. width: 700,
  10. height: 630,
  11. lockY: true,
  12. throttle: 70
  13. }
  14. );
  15. myChart.hideLoading();
  16. var categoryData = [
  17. '北京','天津','河北','山西','内蒙古','辽宁','吉林','黑龙江',
  18. '上海','江苏','浙江','安徽','福建','江西','山东','河南',
  19. '湖北','湖南','广东','广西','海南','重庆','四川','贵州',
  20. '云南','西藏','陕西','甘肃','青海','宁夏','新疆'
  21. ];
  22. option = {
  23. baseOption: {
  24. timeline: {
  25. axisType: 'category',
  26. autoPlay: true,
  27. playInterval: 1000,
  28. data: [
  29. '2002-01-01', '2003-01-01', '2004-01-01',
  30. '2005-01-01', '2006-01-01', '2007-01-01',
  31. '2008-01-01', '2009-01-01', '2010-01-01',
  32. '2011-01-01'
  33. ],
  34. label: {
  35. formatter : function(s) {
  36. return (new Date(s)).getFullYear();
  37. }
  38. }
  39. },
  40. title: {
  41. subtext: 'Media Query 示例'
  42. },
  43. tooltip: {
  44. trigger:'axis',
  45. axisPointer: {
  46. type: 'shadow'
  47. }
  48. },
  49. xAxis: {
  50. type: 'value',
  51. name: 'GDP(亿元)',
  52. max: 30000,
  53. data: null
  54. },
  55. yAxis: {
  56. type: 'category',
  57. data: categoryData,
  58. axisLabel: {interval: 0},
  59. splitLine: {show: false}
  60. },
  61. legend: {
  62. data: ['第一产业', '第二产业', '第三产业', 'GDP', '金融', '房地产'],
  63. selected: {
  64. 'GDP': false, '金融': false, '房地产': false
  65. }
  66. },
  67. calculable : true,
  68. series: [
  69. {name: 'GDP', type: 'bar'},
  70. {name: '金融', type: 'bar'},
  71. {name: '房地产', type: 'bar'},
  72. {name: '第一产业', type: 'bar'},
  73. {name: '第二产业', type: 'bar'},
  74. {name: '第三产业', type: 'bar'},
  75. {name: 'GDP占比', type: 'pie'}
  76. ]
  77. },
  78. media: [
  79. {
  80. option: {
  81. legend: {
  82. orient: 'horizontal',
  83. left: 'right',
  84. itemGap: 10
  85. },
  86. grid: {
  87. left: '10%',
  88. top: 80,
  89. right: 90,
  90. bottom: 100
  91. },
  92. xAxis: {
  93. nameLocation: 'end',
  94. nameGap: 10,
  95. splitNumber: 5,
  96. splitLine: {
  97. show: true
  98. }
  99. },
  100. timeline: {
  101. orient: 'horizontal',
  102. inverse: false,
  103. left: '20%',
  104. right: '20%',
  105. bottom: 10,
  106. height: 40
  107. },
  108. series: [
  109. {name: 'GDP占比', center: ['75%', '30%'], radius: '28%'}
  110. ]
  111. }
  112. },
  113. {
  114. query: {maxWidth: 670, minWidth: 550},
  115. option: {
  116. legend: {
  117. orient: 'horizontal',
  118. left: 200,
  119. itemGap: 5
  120. },
  121. grid: {
  122. left: '10%',
  123. top: 80,
  124. right: 90,
  125. bottom: 100
  126. },
  127. xAxis: {
  128. nameLocation: 'end',
  129. nameGap: 10,
  130. splitNumber: 5,
  131. splitLine: {
  132. show: true
  133. }
  134. },
  135. timeline: {
  136. orient: 'horizontal',
  137. inverse: false,
  138. left: '20%',
  139. right: '20%',
  140. bottom: 10,
  141. height: 40
  142. },
  143. series: [
  144. {name: 'GDP占比', center: ['75%', '30%'], radius: '28%'}
  145. ]
  146. }
  147. },
  148. {
  149. query: {maxWidth: 550},
  150. option: {
  151. legend: {
  152. orient: 'vertical',
  153. left: 'right',
  154. itemGap: 5
  155. },
  156. grid: {
  157. left: 55,
  158. top: '32%',
  159. right: 100,
  160. bottom: 50
  161. },
  162. xAxis: {
  163. nameLocation: 'middle',
  164. nameGap: 25,
  165. splitNumber: 3
  166. },
  167. timeline: {
  168. orient: 'vertical',
  169. inverse: true,
  170. right: 10,
  171. top: 150,
  172. bottom: 10,
  173. width: 55
  174. },
  175. series: [
  176. {name: 'GDP占比', center: ['45%', '20%'], radius: '28%'}
  177. ]
  178. }
  179. }
  180. ],
  181. options: [
  182. {
  183. title: {text: '2002全国宏观经济指标'},
  184. series: [
  185. {data: dataMap.dataGDP['2002']},
  186. {data: dataMap.dataFinancial['2002']},
  187. {data: dataMap.dataEstate['2002']},
  188. {data: dataMap.dataPI['2002']},
  189. {data: dataMap.dataSI['2002']},
  190. {data: dataMap.dataTI['2002']},
  191. {data: [
  192. {name: '第一产业', value: dataMap.dataPI['2002sum']},
  193. {name: '第二产业', value: dataMap.dataSI['2002sum']},
  194. {name: '第三产业', value: dataMap.dataTI['2002sum']}
  195. ]}
  196. ]
  197. },
  198. {
  199. title : {text: '2003全国宏观经济指标'},
  200. series : [
  201. {data: dataMap.dataGDP['2003']},
  202. {data: dataMap.dataFinancial['2003']},
  203. {data: dataMap.dataEstate['2003']},
  204. {data: dataMap.dataPI['2003']},
  205. {data: dataMap.dataSI['2003']},
  206. {data: dataMap.dataTI['2003']},
  207. {data: [
  208. {name: '第一产业', value: dataMap.dataPI['2003sum']},
  209. {name: '第二产业', value: dataMap.dataSI['2003sum']},
  210. {name: '第三产业', value: dataMap.dataTI['2003sum']}
  211. ]}
  212. ]
  213. },
  214. {
  215. title : {text: '2004全国宏观经济指标'},
  216. series : [
  217. {data: dataMap.dataGDP['2004']},
  218. {data: dataMap.dataFinancial['2004']},
  219. {data: dataMap.dataEstate['2004']},
  220. {data: dataMap.dataPI['2004']},
  221. {data: dataMap.dataSI['2004']},
  222. {data: dataMap.dataTI['2004']},
  223. {data: [
  224. {name: '第一产业', value: dataMap.dataPI['2004sum']},
  225. {name: '第二产业', value: dataMap.dataSI['2004sum']},
  226. {name: '第三产业', value: dataMap.dataTI['2004sum']}
  227. ]}
  228. ]
  229. },
  230. {
  231. title : {text: '2005全国宏观经济指标'},
  232. series : [
  233. {data: dataMap.dataGDP['2005']},
  234. {data: dataMap.dataFinancial['2005']},
  235. {data: dataMap.dataEstate['2005']},
  236. {data: dataMap.dataPI['2005']},
  237. {data: dataMap.dataSI['2005']},
  238. {data: dataMap.dataTI['2005']},
  239. {data: [
  240. {name: '第一产业', value: dataMap.dataPI['2005sum']},
  241. {name: '第二产业', value: dataMap.dataSI['2005sum']},
  242. {name: '第三产业', value: dataMap.dataTI['2005sum']}
  243. ]}
  244. ]
  245. },
  246. {
  247. title : {text: '2006全国宏观经济指标'},
  248. series : [
  249. {data: dataMap.dataGDP['2006']},
  250. {data: dataMap.dataFinancial['2006']},
  251. {data: dataMap.dataEstate['2006']},
  252. {data: dataMap.dataPI['2006']},
  253. {data: dataMap.dataSI['2006']},
  254. {data: dataMap.dataTI['2006']},
  255. {data: [
  256. {name: '第一产业', value: dataMap.dataPI['2006sum']},
  257. {name: '第二产业', value: dataMap.dataSI['2006sum']},
  258. {name: '第三产业', value: dataMap.dataTI['2006sum']}
  259. ]}
  260. ]
  261. },
  262. {
  263. title : {text: '2007全国宏观经济指标'},
  264. series : [
  265. {data: dataMap.dataGDP['2007']},
  266. {data: dataMap.dataFinancial['2007']},
  267. {data: dataMap.dataEstate['2007']},
  268. {data: dataMap.dataPI['2007']},
  269. {data: dataMap.dataSI['2007']},
  270. {data: dataMap.dataTI['2007']},
  271. {data: [
  272. {name: '第一产业', value: dataMap.dataPI['2007sum']},
  273. {name: '第二产业', value: dataMap.dataSI['2007sum']},
  274. {name: '第三产业', value: dataMap.dataTI['2007sum']}
  275. ]}
  276. ]
  277. },
  278. {
  279. title : {text: '2008全国宏观经济指标'},
  280. series : [
  281. {data: dataMap.dataGDP['2008']},
  282. {data: dataMap.dataFinancial['2008']},
  283. {data: dataMap.dataEstate['2008']},
  284. {data: dataMap.dataPI['2008']},
  285. {data: dataMap.dataSI['2008']},
  286. {data: dataMap.dataTI['2008']},
  287. {data: [
  288. {name: '第一产业', value: dataMap.dataPI['2008sum']},
  289. {name: '第二产业', value: dataMap.dataSI['2008sum']},
  290. {name: '第三产业', value: dataMap.dataTI['2008sum']}
  291. ]}
  292. ]
  293. },
  294. {
  295. title : {text: '2009全国宏观经济指标'},
  296. series : [
  297. {data: dataMap.dataGDP['2009']},
  298. {data: dataMap.dataFinancial['2009']},
  299. {data: dataMap.dataEstate['2009']},
  300. {data: dataMap.dataPI['2009']},
  301. {data: dataMap.dataSI['2009']},
  302. {data: dataMap.dataTI['2009']},
  303. {data: [
  304. {name: '第一产业', value: dataMap.dataPI['2009sum']},
  305. {name: '第二产业', value: dataMap.dataSI['2009sum']},
  306. {name: '第三产业', value: dataMap.dataTI['2009sum']}
  307. ]}
  308. ]
  309. },
  310. {
  311. title : {text: '2010全国宏观经济指标'},
  312. series : [
  313. {data: dataMap.dataGDP['2010']},
  314. {data: dataMap.dataFinancial['2010']},
  315. {data: dataMap.dataEstate['2010']},
  316. {data: dataMap.dataPI['2010']},
  317. {data: dataMap.dataSI['2010']},
  318. {data: dataMap.dataTI['2010']},
  319. {data: [
  320. {name: '第一产业', value: dataMap.dataPI['2010sum']},
  321. {name: '第二产业', value: dataMap.dataSI['2010sum']},
  322. {name: '第三产业', value: dataMap.dataTI['2010sum']}
  323. ]}
  324. ]
  325. },
  326. {
  327. title : {text: '2011全国宏观经济指标'},
  328. series : [
  329. {data: dataMap.dataGDP['2011']},
  330. {data: dataMap.dataFinancial['2011']},
  331. {data: dataMap.dataEstate['2011']},
  332. {data: dataMap.dataPI['2011']},
  333. {data: dataMap.dataSI['2011']},
  334. {data: dataMap.dataTI['2011']},
  335. {data: [
  336. {name: '第一产业', value: dataMap.dataPI['2011sum']},
  337. {name: '第二产业', value: dataMap.dataSI['2011sum']},
  338. {name: '第三产业', value: dataMap.dataTI['2011sum']}
  339. ]}
  340. ]
  341. }
  342. ]
  343. };
  344. myChart.setOption(option);
  345. });


该分类下的相关小册推荐:

暂无相关推荐.