简介
echarts
根据想要绘制的图表类型,到文档中找相应的配置即可,使用起来比较方便
antV
使用需要理解很多图形化相关的概念、语法。数据驱动,使用灵活,高度易用
- G2可视化引擎:数据驱动,高度易用,可扩展的可视化图形语法
- G6图可视化引擎:便捷的关系数据可视化引擎与图分析工具
- F2移动可视化方案:专注于移动端的可视化解决方案,兼容 H5/小程序/Weex 等多端环境
- L7地理空间数据可视化:高性能/高渲染质量的地理空间数据可视化框架
- G2Plot开箱即用的图标库:开箱即用、易于配置、极致体验的通用图表库
- Viser:基于
G2
实现的可视化解决方案
-
安装:
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
图表组成
- 坐标轴
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
的图表布局如下图
- 创建图表
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],如果nice
为true
,那么就会将数值范围调整为 [0, 100]
min
:{number}
定义数值范围的最小值
max
:{number}
定义数值范围的最大值
minLimit
:{number}
对数据的最小值的限制,无论数据中是否存在比这个值小的数据,生成的坐标点不会小于这个值
maxLimit
:{number}
对数据的最大值的限制,无论数据中是否存在比这个值大的数据,生成的坐标点不会大于这个值
tickCount
:{number}
定义坐标轴刻度线的条数,默认为 5
tickInterval
:{number}
用于指定坐标轴各个刻度点的间距,为原始数据值的差值,tickCount
和tickInterval
不可以同时声明log
:连续非线性的log
类型度量,该度量会将 [1, 10, 100, 1000] 先转换成 [0, 1, 2, 3] 然后再进行归一化操作。log
类型的数据可以将非常大范围的数据映射到一个均匀的范围内
log
度量是linear
的子类,支持所有通用的属性和linear
度量的属性
base
:{number}
基数,默认是 2pow
:连续非线性的pow
类型度量,该度量将 [2, 4, 8, 16, 32] 先转换成 [1, 2, 3, 4, 5] 然后再进行归一化操作
pow
类型的度量也是linear
类型的一个子类
exponent
:{number}
指数,默认是 2time
:连续的时间类型,是一种特殊的连续性数据
time
类型的度量也是linear
的子类
mask
:{string}
指定时间的显示格式,默认:'YYYY-MM-DD'
cat
:分类类型数据的度量
- 拥有通用的度量属性
values
:{array}
指定当前字段的分类值timeCat
:timeCat
度量对应时间数据,但是不是连续的时间类型,而是有序的分类数据
timeCat
是cat
度量的子类
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
:放大、缩小,默认按照坐标系中心放大、缩小transpose
:x
,y
轴交换,例如柱状图转换成水平柱状图(条形图)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 => {})
// ...
发表评论