antV-G2可视化引擎入门笔记

简介

echarts根据想要绘制的图表类型,到文档中找相应的配置即可,使用起来比较方便

antV使用需要理解很多图形化相关的概念、语法。数据驱动,使用灵活,高度易用

  • 安装:npm i @antv/g2 --save

  • 引入:import G2 from '@antv/g2'

  • 创建图表:const chart = new G2.Chart({...})

  • 装载数据:chart.source(data)

  • 使用

this.chart = new G2.Chart({ container: 'c1', width: 600, height: 300 }) const data = [ { genre: 'Sports', sold: 275 }, { genre: 'Strategy', sold: 115 }, { genre: 'Action', sold: 120 }, { genre: 'Shooter', sold: 350 }, { genre: 'Other', sold: 150 } ] // G2 对数据源格式的要求,仅仅是 JSON 数组,数组的每个元素是一个标准 JSON 对象。 // Step 2: 载入数据源 this.chart.source(data) // Step 3:创建图形语法,绘制柱状图,由 genre 和 sold 两个属性决定图形位置,genre 映射至 x 轴,sold 映射至 y 轴 this.chart .interval() .position('genre*sold') .color('genre') // Step 4: 渲染图表 this.chart.render()

G2 文档

图表组成

G2 图表组成

G2图表组成

  • 坐标轴axis:每个坐标轴由坐标轴线(line)、刻度线(tickLine)、刻度文本(label)、标题(title)以及网格线(grid)组成
  • 图例legend:图例作为图表的辅助元素,用于标定不同的数据类型以及数据的范围,用于辅助阅读图表,帮助用户在图表中进行数据的筛选过滤
  • 几何标记geom:即我们所说的点、线、面这些几何图形,在G2中几何标记的类型决定了生成图表的类型。也就是数据被可视化后的实际表现,不同的几何标记都包含对应的图形属性
  • 提示信息tooltip:当鼠标悬停在某个点上时,会以提示框的形式显示当前点对应的数据的信息,比如该点的值,数据单位等。数据提示框内提示的信息还可以通过格式化函数动态指定
  • 辅助标记guide:当需要在图表上绘制一些辅助线、辅助框或者图片时,比如增加平均值线、最高值线或者标示明显的范围区域时,可以使用辅助标记guide

创建图表

  • 图表属性如下
const chart = new G2.Chart({ container: 'c1', // 必选 指定图表容器 可以传入该 DOM 的 id 或者直接传入容器的 HTML 节点对象。 width: {number}, // 指定图表宽度(需要手动设置。如果设置了 forceFit: true,可以不用设置) height: {number}, // 指定图表高度 padding: [10, 20, 30, 40], // 设置图表的内边距,对应 css 样式 padding。上,右,下,左 background: { // 用于设置整个 chart 的图表背景样式,包括边框,背景色,透明度,圆角等; fill: {string}, // 图表背景色 fillOpacity: {number}, // 图表背景透明度 stroke: {string}, // 图表边框颜色 strokeOpacity: {number}, // 图表边框透明度 opacity: {number}, // 图表整体透明度 lineWidth: {number}, // 图表边框粗度 radius: {number}, // 图表圆角大小 } plotBackground: { // 用于设置 chart 绘图区域的背景样式,包括边框,背景色,透明度,圆角等; fill: {string}, // 图表背景色 fillOpacity: {number}, // 图表背景透明度 stroke: {string}, // 图表边框颜色 strokeOpacity: {number}, // 图表边框透明度 opacity: {number}, // 图表整体透明度 lineWidth: {number}, // 图表边框粗度 radius: {number}, // 图表圆角大小 } forceFit: {Boolean}, // 图表的宽度自适应开关,默认为 false,设置为 true 时表示自动取 dom(实例容器)的宽度(此时width无效) animate: {Boolean}, // 图表动画开关,默认为 true,即开启动画。 data: [ // 直接装载数据,常用的是调用 chart.source(data) 方法 // ... ] })
  • G2的图表布局如下图

G2图表布局

  • 创建图表
this.chart = new G2.Chart({ container: 'c1', width: 600, height: 300 })

装载数据

  • 方式一:data属性传入
const chart = new G2.Chart({ id: 'c1', width: 600, height: 300, data: [ { x: 'a', y: 1 }, { x: 'b', y: 2 }, ... ] });
  • 方式二:调用chart.source(data)方法,每个字段的列定义也可以在这里传入
chart.source(data, { x: { type: 'cat' }, y: { min: 0 } })

G2支持两种格式的数据源:JSON数组、DataView对象

更新数据:

  • chart.changeData(data):马上更新图表
  • view.changeData(data)view也支持
  • 不需要马上更新可以:chart.source(data),需要更新的时候chart.repaint()
  • chart.clear():清理所有
  • chart.render():绘制

DataSet

术语

英文 英文 描述
数据集 DataSet 一组数据集合
数据视图 DataView 单个数据视图,目前有普通二维数据(类似一张数据库表)、树形数据、图数据和地理信息数据几种类型
状态量 state 数据集内部流转的控制数据状态的变量
变换 Transform 数据变换函数,数据视图做数据处理时使用,包括图布局、数据补全、数据过滤等等
连接器 Connector 数据接入函数,用于把某种数据源(譬如 csv)载入到某个数据视图上

DataSet相关参考:DataSet

  • 数据连接(Connector):负责导入和归一化数据(譬如导入CSV数据,导入GeoJSON数据等)。参考链接:Connector 数据接入
  • 数据转换(Transform):负责进行各种数据转换操作(譬如图布局、数据统计、数据补全等)。参考链接:Transform 数据转换

DataSet完成功能:

  • 源数据的解析,将CSV, DSV, GeoJSON转成标准的JSON
  • 加工数据,包括filter, map, fold(补数据) 等操作
  • 统计函数,汇总统计、百分比、封箱 等统计函数
  • 特殊数据处理,包括 地理数据、矩形树图、桑基图、文字云 的数据处理
  • 安装:npm install @antv/data-set --save

  • 引入

import { View } from '@antv/data-set' const dv = new View()
  • 图表联动时,使用状态量
// step1 创建 dataset 指定状态量 const ds = new DataSet({ state: { year: '2010' } }); // step2 创建 DataView const dv = ds.createView().source(data); dv.transform({ type: 'filter', callback(row) { return row.year === ds.state.year; } }); // step3 引用 DataView chart.source(dv); // step4 更新状态量 ds.setState('year', '2012');

Transform常用处理

  • filter数据过滤
dv.transform({ type: 'filter', callback(row) { // 判断某一行是否保留,默认返回true return row.year ? 1998 } })
  • map数据加工
dv.transform({ type: 'map', callback(row) { // 加工数据后返回新的一行,默认返回行数据本身 row.newCol = row.xx + row.yy return row } })
  • pick字段过滤
dv.transform({ type: 'pick', fields: ['xxx', 'yyy'] // 决定保留哪些字段,如果不传,则返回所有字段 })
  • rename字段重命名(alias:rename-fields
dv.transform({ type: 'rename', map: { xxx: 'yyy' // row.xxx 会被替换成 row.yyy } })
  • reverse逆序排列
dv.transform({ // 把数据行逆序排列 type: 'reverse' })
  • sort数据排序
dv.transform({ type: 'sort', callback(a, b) { // 排序依据,和原生js的排序callback一致 return a.year - b.year } })
  • sort-by按字段排序(alias:sortBy
dv.transform({ type: 'sort-by', fields: ['year'], // 根据指定的字段集进行排序,与lodash的sortBy行为一致 order: 'DESC' // 默认为 ASC,DESC则为逆序 })
  • subset获取子集
dv.transform({ type: 'subset', startRowIndex: 1, // 保留行的起始索引 endRowIndex: 2, // 保留行的结束索引 fields: ['year'] // 保留字段集 })
  • partition数据分组(alias:group | groups
dv.transform({ type: 'partition', groupBy: ['year'], // 以 year 字段进行分组 orderBy: ['month'] // 以 month 字段进行排序 })
  • fold字段展开(以指定字段集为key,展开数据)
const data = [ { country: 'USA', gold: 10, silver: 20 }, { country: 'Canada', gold: 7, silver: 26 } ] const dv = ds.createView().source(data) .transform({ type: 'fold', fields: ['gold', 'silver'], // 展开字段集 key: 'key', // key 字段 value: 'value', // value 字段 retains: ['country'] // 保留字段集,默认为除 fields 以外的所有字段 }) /** * dv.rows 变为 * [ * { key: gold, value: 10, country: 'USA' }, * { key: silver, value: 20, country: 'USA' }, * { key: gold, value: 7, country: 'Canada' }, * { key: silver, value: 26, country: 'Canada' } * ] */
  • percent总和百分比
dv.transform({ type: 'percent', field: 'sold', // 统计销量 dimension: 'year', // 每年的占比 groupBy: ['category'], // 以不同的产品类别为分组,每个分组内部各自统计占比 as: 'percent' // 结果存储在 percent 字段 })

示例

import G2 from '@antv/g2' import DataSet from '@antv/data-set' const data = `State,小于5岁,5至13岁,14至17岁,18至24岁,25至44岁,45至64岁,65岁及以上 WY,38253,60890,29314,53980,137338,147279,65614 DC,36352,50439,25225,75569,193557,140043,70648 VT,32635,62538,33757,61679,155419,188593,86649 ND,41896,67358,33794,82629,154913,166615,94276 AK,52083,85640,42153,74257,198724,183159,50277 SD,58566,94438,45305,82869,196738,210178,116100` // const data = [ // { 'State': 'WY', '小于5岁': 38253, '5至13岁': 60890, '14至17岁': 29314, '18至24岁': 53980, '25至44岁': 137338, '45至64岁': 147279, '65岁及以上': 65614 }, // { 'State': 'DC', '小于5岁': 36352, '5至13岁': 50439, '14至17岁': 25225, '18至24岁': 75569, '25至44岁': 193557, '45至64岁': 140043, '65岁及以上': 70648 }, // { 'State': 'VT', '小于5岁': 32635, '5至13岁': 62538, '14至17岁': 33757, '18至24岁': 61679, '25至44岁': 155419, '45至64岁': 188593, '65岁及以上': 86649 }, // { 'State': 'ND', '小于5岁': 41896, '5至13岁': 67358, '14至17岁': 33794, '18至24岁': 82629, '25至44岁': 154913, '45至64岁': 166615, '65岁及以上': 94276 }, // { 'State': 'AK', '小于5岁': 52083, '5至13岁': 85640, '14至17岁': 42153, '18至24岁': 74257, '25至44岁': 198724, '45至64岁': 183159, '65岁及以上': 50277 }, // { 'State': 'SD', '小于5岁': 58566, '5至13岁': 94438, '14至17岁': 45305, '18至24岁': 82869, '25至44岁': 196738, '45至64岁': 210178, '65岁及以上': 116100 } // ] this.ds = new DataSet({ state: { currentState: 'WY' } }) const dvForAll = that.ds.createView('populationByAge', { watchingStates: [] }) // .source(data) .source(data, { type: 'csv' }) // 将字符串转为数字 dvForAll.transform({ type: 'map', callback(row) { for (const key in row) { if (key !== 'State') { row[key] = Number(row[key]) } } return row } }) dvForAll.transform({ type: 'fold', fields: [`小于5岁`, `5至13岁`, `14至17岁`, `18至24岁`, `25至44岁`, `45至64岁`, `65岁及以上`], key: 'age', value: 'population' }) const dvForOneState = that.ds.createView('populationOfOneState').source(dvForAll) dvForOneState.transform({ type: 'filter', callback(row) { return row.State === that.ds.state.currentState } }).transform({ type: 'percent', field: 'population', dimension: 'age', as: 'percent' }) // 使用 G2 绘图、绑定事件 const c1 = new G2.Chart({ id: 'c1', forceFit: true, height: 300 }) c1.source(dvForAll) c1.legend({ position: 'top' }) c1.axis('population', { label: { formatter: val => { let numVal = Number(val) return Math.floor(numVal / 1000) + 'M' // return val / 1000000 + 'M' } } }) // 层叠柱状图 https://www.yuque.com/antv/g2-docs/tutorial-geom-and-adjust c1.intervalStack() .position('State*population') .color('age') .select(true, { mode: 'single', style: { stroke: 'red', strokeWidth: 5 } }) c1.on('tooltip:change', function(evt) { const items = evt.items || [] if (items[0]) { that.ds.setState('currentState', items[0].title) } }) const c2 = new G2.Chart({ id: 'c2', forceFit: true, height: 300, padding: 0 }) c2.source(dvForOneState) // 重要:绘制饼图时,必须声明 theta 坐标系 c2.coord('theta', { radius: 0.8 }) c2.legend(false) c2.intervalStack() .position('percent') .color('age') .label('age*percent', function(age, percent) { percent = (percent * 100).toFixed(2) + '%' return age + ' ' + percent }) c1.render() c2.render()

度量Scale

通用属性配置

  • type{string} 度量类型
  • range{array} 数值范围区间,即度量转换的范围,默认为[0, 1]
  • alias{string} 为数据属性定义别名,用于图例、坐标轴、tooltip的个性化显示
  • ticks{array} 存储坐标轴上的刻度点文本信息
  • tickCount{number} 坐标轴上刻度点的个数,不同的度量类型对应不同的默认值
  • formatter{function} 回调函数,用于格式化坐标轴刻度点的文本显示,会影响数据在坐标轴、图例、tooltip上的显示

度量的类型

  • linear:连续的数据值
    • nice: {boolean}默认为true,用于优化数值范围,使绘制的坐标轴刻度线均匀分布。例如原始数据的范围为 [3, 97],如果 nicetrue,那么就会将数值范围调整为 [0, 100]
    • min{number}定义数值范围的最小值
    • max{number}定义数值范围的最大值
    • minLimit{number}对数据的最小值的限制,无论数据中是否存在比这个值小的数据,生成的坐标点不会小于这个值
    • maxLimit{number}对数据的最大值的限制,无论数据中是否存在比这个值大的数据,生成的坐标点不会大于这个值
    • tickCount{number}定义坐标轴刻度线的条数,默认为 5
    • tickInterval{number}用于指定坐标轴各个刻度点的间距,为原始数据值的差值,tickCounttickInterval 不可以同时声明
  • log:连续非线性的 log 类型度量,该度量会将 [1, 10, 100, 1000] 先转换成 [0, 1, 2, 3] 然后再进行归一化操作。log 类型的数据可以将非常大范围的数据映射到一个均匀的范围内
    • log 度量是 linear 的子类,支持所有通用的属性和 linear 度量的属性
    • base{number}基数,默认是 2
  • pow:连续非线性的 pow 类型度量,该度量将 [2, 4, 8, 16, 32] 先转换成 [1, 2, 3, 4, 5] 然后再进行归一化操作
    • pow 类型的度量也是 linear 类型的一个子类
    • exponent{number}指数,默认是 2
  • time:连续的时间类型,是一种特殊的连续性数据
    • time 类型的度量也是 linear 的子类
    • mask{string}指定时间的显示格式,默认:'YYYY-MM-DD'
  • cat:分类类型数据的度量
    • 拥有通用的度量属性
    • values{array}指定当前字段的分类值
  • timeCattimeCat 度量对应时间数据,但是不是连续的时间类型,而是有序的分类数据
    • timeCatcat 度量的子类
    • mask{string}指定时间的显示格式,默认:'YYYY-MM-DD'

Geom几何标记

几何标记类型

geom 类型 描述
point 点,用于绘制各种点图
path 路径,无序的点连接而成的一条线,常用于路径图的绘制
line 线,点按照 x 轴连接成一条线,构成线图
area 填充线图跟坐标系之间构成区域图,也可以指定上下范围
interval 使用矩形或者弧形,用面积来表示大小关系的图形,一般构成柱状图、饼图等图表
polygon 多边形,可以用于构建色块图、地图等图表类型
edge 两个点之间的链接,用于构建树图和关系图中的边、流程图中的连接线
schema 自定义图形,用于构建箱型图(或者称箱须图)、蜡烛图(或者称 K 线图、股票图)等图表
heatmap 用于热力图的绘制

Coord坐标系

chart.coord('coordType'[, cfg]); chart.coord().rotate(90).scale(1.3, 5).reflect('x').transpose();

类型说明

  • rect: 直角坐标系,目前仅支持二维,由 x, y 两个互相垂直的坐标轴构成
  • polar: 极坐标系,由角度和半径 2 个维度构成
  • theta: 一种特殊的极坐标系,半径长度固定,仅仅将数据映射到角度,常用于饼图的绘制
  • helix: 螺旋坐标系,基于阿基米德螺旋线

变换操作

  • rotate:旋转,默认按照坐标系中心旋转
  • scale:放大、缩小,默认按照坐标系中心放大、缩小
  • transposexy 轴交换,例如柱状图转换成水平柱状图(条形图)
  • reflect:镜像, 沿 x 方向镜像或者沿 y 轴方向映射

详细教程见:Coord 坐标系

坐标轴axis

坐标轴组成

  • 标题title
  • 坐标轴线line
  • 文本label
  • 刻度线tickLine
  • 网格grid

坐标轴的组成

// 标题 title chart.axis('xField', { title: null // 不展示 xField 对应坐标轴的标题 }) chart.axis('xField', { title: {} // 展示 xField 对应坐标轴的标题 }) chart.axis('xField', { title: { textStyle: { fontSize: 12, // 文本大小 textAlign: 'center', // 文本对齐方式 fill: '#999', // 文本颜色 // ... } } }) // 标题别名 chart.scale('xField', { alias: '这里设置标题的别名' }) // 坐标轴线line chart.axis('xField', { line: { lineWidth: 2, // 设置线的宽度 stroke: 'red', // 设置线的颜色 lineDash: [ 3, 3 ] // 设置虚线样式 } }) // 坐标轴文本label chart.axis('xField', { label: null // 不展示文本 }) chart.axis('xField', { label: { offset: {number}, // 设置坐标轴文本 label 距离坐标轴线的距离 textStyle: { textAlign: 'center', // 文本对齐方向,可取值为: start middle end fill: '#404040', // 文本的颜色 fontSize: '12', // 文本大小 fontWeight: 'bold', // 文本粗细 rotate: 30, textBaseline: 'top' // 文本基准线,可取 top middle bottom,默认为middle } || {function}, // 文本样式,支持回调 autoRotate: {boolean} // 是否需要自动旋转,默认为 true } }) chart.axis('xField', { label: { // 使用 formatter 回调函数 formatter: val => { return val + '元'; } } }) // 在坐标轴上配置 formatter 仅在坐标轴上的文本有效,如果想要使得 tooltip 和图例上的信息也格式化,需要在列定义时指定格式化函数 chart.source(data, { xField: { formatter: val => { return val + '元'; } } }) // 或者 chart.scale('xField', { formatter: val => { return val + '元'; } }) // 自定义label chart.axis('xField', { label: { htmlTemplate: value => { return '<img src="' +imageMap[value] + '" width="30px"/>'; } } }) // 坐标轴刻度线tickLine chart.axis('xField', { tickLine: { lineWidth: 2, length: 10, // 可以设置负值,使得tickLine的方向相反 stroke: 'red', alignWithLabel: true } }) // 坐标轴子刻度线subTickLine chart.axis('xField', { subTickCount: 3, subTickLine: { length: 3, stroke: '#545454', lineWidth: 1 }, tickLine: { length: 5, lineWidth: 2, stroke: '#000' } }) // 网格grid chart.axis('xField', { grid: { type: 'line', lineStyle: { stroke: '#d9d9d9', lineWidth: 1, lineDash: [ 4, 4 ] }, align: 'center' // 网格顶点从两个刻度中间开始 } })

详细教程见:Axis 坐标轴

图例legend

详细教程见:Legend 图例

几何标记geom

详细教程见:Geom 几何标记

提示信息tooltip

详细教程见:Tooltip 提示信息

辅助标记guide

详细教程见:Guide 辅助元素

图表事件

chart.on('eventType', fn) // 绑定事件 chart.off('eventType', fn) // 移除事件 // 画布基础事件 chart.on('mousedown', ev => {}) chart.on('mousemove', ev => {}) chart.on('mouseleave', ev => {}) chart.on('mouseup', ev => {}) chart.on('click', ev => {}) chart.on('dblclick', ev => {}) chart.on('touchstart', ev => {}) chart.on('touchmove', ev => {}) chart.on('touchend', ev => {}) // 绘图区域事件 chart.on('plotenter', ev => {}) chart.on('plotmove', ev => {}) chart.on('plotleave', ev => {}) chart.on('plotclick', ev => {}) chart.on('plotdblclick', ev => {}) // tooltip 事件 chart.on('tooltip:show', ev => {}) // tooltip 展示 chart.on('tooltip:hide', ev => {}) // tooltip 隐藏 chart.on('tooltip:change', ev => {}) // tooltip 内容发生变化的时候 // 图形元素事件 chart.on('point:click', ev => {}) chart.on('axis-label:click', ev => {}) // ...

创作不易,若本文对你有帮助,欢迎打赏支持作者!

 分享给好友: