在图表样式上,G2 提供了丰富的自定义配置选项,既可从全局设置,也支持 Chart 级别的主题设置和局部设置数据层级的设置。

图表主题

G2 默认提供了两种图表主题: default、dark。Theme 图表皮肤 - 图1

图表样式设置

新增主题

新增主题可以使用 Global 上的 registerTheme 接口。

  1. const { Global } = G2; // 获取 Global 全局对象
  2. Global.registerTheme('newTheme', {
  3. colors: [ 'red', 'blue', 'yello' ]
  4. }); // 传入两个参数,一个参数是主题的名称,另一个参数是主题配置项

这样就可以在全局切换这个主题或者在 chart 新建的时候指定设置的主题了。

全局图表主题切换

直接传入主题名

  1. const { Global } = G2; // 获取 Global 全局对象
  2. Global.setTheme('dark'); // 传入值为 'default'、'dark' 的一种,如果不是,那么使用 default 主题。

变更全局样式

G2 图表样式的配置项都是设置到全局变量 G2.Global 上,可以通过如下两种方式进行局部的样式设置:

(1)方式一: 直接赋值给全局对象 Global,但是不推荐

  1. G2.Global.animate = false ; // 关闭默认动画
  2. G2.Global.colors = [ 'red', 'blue', 'yellow' ]; // 更改默认的颜色

(2) 方式二: 使用 Global.setTheme 方法。推荐使用这种方式,使用方法如下:

  1. const theme = G2.Util.deepMix({
  2. animate: false,
  3. colors: {...},
  4. shapes: {...}
  5. // 具体的配置项详见 api/global.html
  6. }, G2.Theme);
  7. G2.Global.setTheme(theme); // 将主题设置为用户自定义的主题

对于数据级别或者更细粒度的样式设置,可以通过 geom 对象上的 color 图形属性方法或者各个 chart 配置项上的图形属性设置。

更多 Global 上关于主题的配置属性,可以直接查看 G2.Global 的返回值。

demo 演示

Theme 图表皮肤 - 图2

  1. const Util = G2.Util;
  2. const theme = Util.deepMix({
  3. shape: {
  4. polygon: {
  5. stroke: '#213c51', // 地图轮廓线颜色
  6. lineWidth: 1 // 地图轮廓线宽度
  7. },
  8. hollowPoint: {
  9. fill: '#21273b', // 点的填充颜色
  10. lineWidth: 2, // 点的边框宽度
  11. radius: 3 // 点的半径
  12. },
  13. interval: {
  14. fillOpacity: 1 // 填充透明度设置
  15. }
  16. },
  17. axis: {
  18. bottom: {
  19. label: {
  20. textStyle: { fill: '#999'} // 底部标签文本的颜色
  21. }
  22. },
  23. left: {
  24. label: {
  25. textStyle: { fill: '#999'} // 左部标签文本的颜色
  26. }
  27. },
  28. right: {
  29. label: {
  30. textStyle: { fill: '#999'} // 右部标签文本的颜色
  31. }
  32. }
  33. }
  34. }, G2.Global);
  35. G2.Global.setTheme(theme);
  36. $.getJSON('/assets/data/world.geo.json', function(mapData) {
  37. const userData = [];
  38. const features = mapData.features;
  39. for(let i=0; i<features.length; i++) {
  40. const name = features[i].properties.name;
  41. userData.push({
  42. "name": name,
  43. "value": Math.round(Math.random()*1000)
  44. });
  45. }
  46. // 绘制地图背景
  47. const ds = new DataSet();
  48. const bgDataView = ds.createView('back')
  49. .source(mapData, {
  50. type: 'GeoJSON'
  51. })
  52. .transform({
  53. type: 'geo.projection',
  54. projection: 'geoMercator'
  55. });
  56. const userPolygonDv = ds.createView()
  57. .source(userData)
  58. .transform({
  59. geoDataView: bgDataView,
  60. field: 'name',
  61. type: 'geo.region',
  62. as: [ 'longitude', 'latitude' ]
  63. });
  64. const chart = new G2.Chart({
  65. container: 'c1',
  66. forceFit: true,
  67. height: 400,
  68. padding: 0
  69. });
  70. chart.source(userPolygonDv);
  71. chart.coord().reflect();
  72. chart.tooltip({
  73. showTitle: false
  74. });
  75. chart.axis(false);
  76. chart.legend(false);
  77. chart.polygon()
  78. .position('longitude*latitude')
  79. .color('value','#39ccf4-#20546b')
  80. .style({
  81. lineWidth: 1,
  82. stroke: '#999'
  83. });
  84. chart.render();
  85. const data = [
  86. { time: '10:10', call: 4, waiting: 2, people: 2 },
  87. { time: '10:15', call: 2, waiting: 6, people: 3 },
  88. { time: '10:20', call: 13, waiting: 2, people: 5 },
  89. { time: '10:25', call: 9, waiting: 9, people: 1 },
  90. { time: '10:30', call: 5, waiting: 2, people: 3 },
  91. { time: '10:35', call: 8, waiting: 2, people: 1 },
  92. { time: '10:40', call: 13, waiting: 1, people: 2 }
  93. ];
  94. const dv = new DataSet.DataView();
  95. dv.source(data).transform({
  96. type: 'fold',
  97. fields: [ 'call','waiting' ],
  98. key: 'type',
  99. value: 'count',
  100. retains: [ 'time', 'people' ]
  101. });
  102. const chart2 = new G2.Chart({
  103. container: 'c2',
  104. forceFit: true,
  105. height: 250
  106. });
  107. chart2.source(dv, {
  108. 'count': { alias: '话务量(通)', min: 0 },
  109. 'people': { alias: '人数(人)', min: 0 }
  110. });
  111. chart2.legend(false);// 不显示图例
  112. chart2.intervalStack().position('time*count').color('type', [ '#348cd1', '#43b5d8' ]); // 绘制层叠柱状图
  113. chart2.line().position('time*people').color('#5ed470').size(4).shape('smooth'); // 绘制曲线图
  114. chart2.point().position('time*people').color('#5ed470').tooltip(false); // 绘制点图
  115. chart2.render();
  116. });

Global 上可以配置的信息:

  • 全局的控制变量:柱子的默认宽度、版本号、折线图遇到 Null 时的处理策略
  1. const Global = {
  2. version: '3.2.0-beta.3',
  3. renderer2d: 'canvas',
  4. // renderer2d: 'svg',
  5. trackable: true,
  6. animate: true,
  7. snapArray: [ 0, 1, 2, 4, 5, 10 ],
  8. // 指定固定 tick 数的逼近值
  9. snapCountArray: [ 0, 1, 1.2, 1.5, 1.6, 2, 2.2, 2.4, 2.5, 3, 4, 5, 6, 7.5, 8, 10 ],
  10. widthRatio: { // 宽度所占的分类的比例
  11. column: 1 / 2, // 一般的柱状图占比 1/2
  12. rose: 0.9999999, // 玫瑰图柱状占比 1
  13. multiplePie: 1 / 1.3 // 多层的饼图、环图
  14. },
  15. // 折线图、区域图、path 当只有一个数据时,是否显示成点
  16. showSinglePoint: false,
  17. connectNulls: false,
  18. scales: {
  19. }
  20. };

更多的查看:https://github.com/antvis/g2/blob/master/src/global.js

Chart 级别主题切换

同一个上下文现在支持多种主题共存,上述两个图表,通过给第二个图表指定主题,可以切换其主题:

  1. const chart2 = new G2.Chart({
  2. container: 'c2',
  3. forceFit: true,
  4. height: 250,
  5. theme: 'dark'
  6. });

Theme 图表皮肤 - 图3

  1. const Util = G2.Util;
  2. const theme = Util.deepMix({
  3. shape: {
  4. polygon: {
  5. stroke: '#213c51', // 地图轮廓线颜色
  6. lineWidth: 1 // 地图轮廓线宽度
  7. },
  8. hollowPoint: {
  9. fill: '#21273b', // 点的填充颜色
  10. lineWidth: 2, // 点的边框宽度
  11. radius: 3 // 点的半径
  12. },
  13. interval: {
  14. fillOpacity: 1 // 填充透明度设置
  15. }
  16. },
  17. axis: {
  18. bottom: {
  19. label: {
  20. textStyle: { fill: '#999'} // 底部标签文本的颜色
  21. }
  22. },
  23. left: {
  24. label: {
  25. textStyle: { fill: '#999'} // 左部标签文本的颜色
  26. }
  27. },
  28. right: {
  29. label: {
  30. textStyle: { fill: '#999'} // 右部标签文本的颜色
  31. }
  32. }
  33. }
  34. }, G2.Global);
  35. G2.Global.setTheme(theme);
  36. $.getJSON('/assets/data/world.geo.json', function(mapData) {
  37. const userData = [];
  38. const features = mapData.features;
  39. for(let i=0; i<features.length; i++) {
  40. const name = features[i].properties.name;
  41. userData.push({
  42. "name": name,
  43. "value": Math.round(Math.random()*1000)
  44. });
  45. }
  46. // 绘制地图背景
  47. const ds = new DataSet();
  48. const bgDataView = ds.createView('back')
  49. .source(mapData, {
  50. type: 'GeoJSON'
  51. })
  52. .transform({
  53. type: 'geo.projection',
  54. projection: 'geoMercator'
  55. });
  56. const userPolygonDv = ds.createView()
  57. .source(userData)
  58. .transform({
  59. geoDataView: bgDataView,
  60. field: 'name',
  61. type: 'geo.region',
  62. as: [ 'longitude', 'latitude' ]
  63. });
  64. const chart = new G2.Chart({
  65. container: 'c3',
  66. forceFit: true,
  67. height: 400,
  68. padding: 0
  69. });
  70. chart.source(userPolygonDv);
  71. chart.coord().reflect();
  72. chart.tooltip({
  73. showTitle: false
  74. });
  75. chart.axis(false);
  76. chart.legend(false);
  77. chart.polygon()
  78. .position('longitude*latitude')
  79. .color('value','#39ccf4-#20546b')
  80. .style({
  81. lineWidth: 1,
  82. stroke: '#999'
  83. });
  84. chart.render();
  85. const data = [
  86. { time: '10:10', call: 4, waiting: 2, people: 2 },
  87. { time: '10:15', call: 2, waiting: 6, people: 3 },
  88. { time: '10:20', call: 13, waiting: 2, people: 5 },
  89. { time: '10:25', call: 9, waiting: 9, people: 1 },
  90. { time: '10:30', call: 5, waiting: 2, people: 3 },
  91. { time: '10:35', call: 8, waiting: 2, people: 1 },
  92. { time: '10:40', call: 13, waiting: 1, people: 2 }
  93. ];
  94. const dv = new DataSet.DataView();
  95. dv.source(data).transform({
  96. type: 'fold',
  97. fields: [ 'call','waiting' ],
  98. key: 'type',
  99. value: 'count',
  100. retains: [ 'time', 'people' ]
  101. });
  102. const chart2 = new G2.Chart({
  103. container: 'c4',
  104. forceFit: true,
  105. height: 250,
  106. theme: 'dark'
  107. });
  108. chart2.source(dv, {
  109. 'count': { alias: '话务量(通)', min: 0 },
  110. 'people': { alias: '人数(人)', min: 0 }
  111. });
  112. chart2.legend(false);// 不显示图例
  113. chart2.intervalStack().position('time*count').color('type', [ '#348cd1', '#43b5d8' ]); // 绘制层叠柱状图
  114. chart2.line().position('time*people').color('#5ed470').size(4).shape('smooth'); // 绘制曲线图
  115. chart2.point().position('time*people').color('#5ed470').tooltip(false); // 绘制点图
  116. chart2.render();
  117. });