最近公司在手机端做一个统计报表,需要通过图形展示,之前我使用了百度echart最多,相对来说比较熟悉,文档比较全,社区也比较活跃,后台公司决定使用蚂蚁金服的G2数据可视化图表,从直观上图标显示的效果在手机端上更友好些
G2简介
G2 是一套基于图形语法理论的可视化底层引擎,以数据驱动,提供图形语法与交互语法,具有高度的易用性和扩展性。使用 G2,你可以无需关注图表各种繁琐的实现细节,一条语句即可使用 Canvas 或 SVG 构建出各种各样的可交互的统计图表。
G2基本使用
- 安装
npm install @antv/g2@4.0.15 --save
- 使用
//template <div id="c1"></div> import { Chart } from '@antv/g2'; const data = [ { genre: 'Sports', sold: 275 }, { genre: 'Strategy', sold: 115 }, { genre: 'Action', sold: 120 }, { genre: 'Shooter', sold: 350 }, { genre: 'Other', sold: 150 }, ]; // Step 1: 创建 Chart 对象 const chart = new Chart({ container: 'c1', // 指定图表容器 ID width: 600, // 指定图表宽度 height: 300, // 指定图表高度 }); // Step 2: 载入数据源 chart.data(data); // Step 3: 创建图形语法,绘制柱状图 chart.interval().position('genre*sold'); // Step 4: 渲染图表 chart.render();
G2基本配置
- Chart图表的属性
const chart = new G2.Chart({
container: 'c1', // 必选 指定图表容器 可以传入该 DOM 的 id 或者直接传入容器的 HTML 节点对象。
width : {number}, // 指定图表宽度
height : {number}, // 指定图表高度
padding:[10,20,30,40], //设置图表的内边距,对应css样式padding
background: {
fill: {string}, // 图表背景色
fillOpacity: {number}, // 图表背景透明度
stroke: {string}, // 图表边框颜色
strokeOpacity: {number}, // 图表边框透明度
opacity: {number}, // 图表整体透明度
lineWidth: {number}, // 图表边框粗度
radius: {number}, // 图表圆角大小
},
forceFit: {Boolean}, //图表的宽度自适应开关,默认为 false,设置为 true 时表示自动取 dom(实例容器)的宽度.
animate: {Boolean}, //图表动画开关,默认为 true,即开启动画。
})
- Chart的常用方法
-
chart.source(data, scaleConfig)
- data
数据源数据,标准的 JSON 数组或者 DataSet.View 对象。 - scaleConfig
可选,用于数据字段的列定义,如设置数据的类型,显示别名,时间类型的展示格式等,不同的数字类型的配置项不同,详情可配置属性参考Chart文档 Scale。
- data
-
chart.data(data);载入数据
-
chart.axis 坐标轴的配置
chart.axis(false)
关闭坐标轴
chart.axis('field', false)
不展示 field 字段对应的坐标轴。
chart.axis('field', axisConfig)
一个对象类型,用于设置坐标轴配置信息,可配置属性如下:
position: string 设置坐标轴的显示位置,可设置的值包含 top、bottom、left、right,即上下左右四个位置。
line: object |null 设置坐标轴线的样式,包括线的颜色、粗细等。如果该属性值为 null 则表示不展示坐标轴线。
label: object |null 设置坐标轴文本的样式。如果该属性值为 null 则表示不展示坐标轴文本。
title: object |null 设置坐标轴标题的显示样式。如果该属性值为 null 则表示不展示坐标轴标题。
tickLine: object |null 设置坐标轴的刻度线。如果该属性值为 null 则表示不展示。
subTickCount: number 设置每两个刻度之间次刻度线的个数,默认为 0,即不展示次刻度线。
subTickLine: number 设置每两个刻度之间次刻度线的个数,默认为 0,即不展示次刻度线。
grid: object | null 设置坐标轴网格线的样式,网格线与坐标轴线垂直。如果该属性值为 null 则表示不展示。
- chart.tooltip
chart.tooltip(false)
关闭 tooltip 功能。
chart.tooltip(tooltipConfig)
是一个对象类型,支持的属性如下:
triggerOn: string tooltip的触发方式,可配置的值为:’mousemove’、’click’、’none’,默认为 mousemove。
showTitle: boolean 是否展示提示信息的标题,默认为 true,即展示,通过设置为 false 来隐藏标题。
title: string 设置 tooltip 的标题展示的数据字段,设置该字段后,该标题即会展示该字段对应的数值。showTitle 为 false 时,该设置不生效。
offset: number 设置 tooltip 距离鼠标的偏移量。
inPlot: boolean 设置是否将 tooltip 限定在绘图区域内,默认为 true,即限定在绘图区域内。
follow: boolean 设置 tooltip 是否跟随鼠标移动。默认为 true,即跟随。
shared: boolean 设置 tooltip 只展示单条数据。
enterable: boolean 用于控制是否允许鼠标进入 tooltip,默认为 false,即不允许进入。
position: string 该属性设置之后,就会在固定位置展示 tooltip,可设置的值为:left、right、top、bottom。
follow: 设置 tooltip 是否跟随鼠标移动。默认为 true,即跟随。
根据不同的需求在G2官网查看对应的配置
vue在使用G2的问题
-
基本的配置使用,改变什么字体颜色,位置,显示格式化问题。
通过查看基本配置可以解决。 -
数据在图表显示的 比例协调性
通过数据的动态显示图标的最大值,解决显示数据协调问题。 -
异步数据加载问题,第一次加载不显示
微信图片_20210115104438.png
因为vue的组件是异步渲染
机制,要确保在 props 传过来的值 第一次变化后的,才去渲染 G2的图标库;由于 watch监听数据的变化比created钩子还要早,那个时候vue组件还没有挂载组件的根dom,所以才会导致 G2底层获取组件中的dom时报错;
报错如下:
解决思路:因为是获取dom元素时机导致的,我们可以在通过watch监听同时通过 vue提供的 this.$nextTick()解决确保vue组件的dom加载完成。
-
异步数据 切换时, 图形叠加问题
- 通过 每次调用接口时,清除数据为空,则解决。
但是会影响用户体验,需要重新加载G2的,会导致闪屏可能性出现。 - 通过 G2给我们提供一个方法 chart.changeData(data);可以重载数据不需要销毁掉当前chart实例。
我们可以在watch 监听同时,判断是否第一次加载,如果第一次加载chart,下次就直接可以 重载数据。
这样解决目的保证 图表每次切换时,不会出现闪屏,很友好过渡切换,增加用户体验感。
- 通过 每次调用接口时,清除数据为空,则解决。
vue中使用G2条形图栗子
<template>
<div id="chart3"></div>
</template>
<script>
import { Chart } from '@antv/g2';
export default {
name:"bar",
props:["list","max"],
data() {
return {
chart: null,//把chart实例挂在当前组件
first: true// 区分第一次chart加载
}
},
watch: {
list: {
// 解决问题 3 4
handler: function (newVal, oldVal) {
this.$nextTick(function(){
if(this.first) {
this.drawLine(newVal);
}else {
this.chart.changeData(newVal);
}
})
},
immediate: true,
deep:true
}
},
methods: {
drawLine(list) {
console.log("drawLine",list)
// console.log(this.list,this.max)
let max = this.max;
// let max = 0;
this.chart = new Chart({
container: 'chart3',
autoFit: true,
height: 460,
padding: [0, 0, 0, 100], // 上,右,下,左
});
this.chart.forceFit()
this.chart.data(list);
this.chart.scale({
value: {
max: max,
min: 0,
alias: '销量(个)',
},
});
this.chart.tooltip({
showMarkers: false, // 不展示 tooltip markers
});
this.chart.interaction('active-region'); // 使用 active-region 交互行为
this.chart.axis('type',{
tickLine: null,
line:null,
label: {
style: {
fill:"#222",
fontSize: 14,
fontWeight: 600,
fontFamily:"PingFang-SC-Medium"
}
}
});
this.chart.axis('value', {
label: null,
title: {
offset: 30,
style: {
fontSize: 14,
fontWeight: 600,
},
},
grid:null
});
this.chart.legend(false);
this.chart.coordinate().transpose();
this.chart
.interval()
.position('type*value')
.color('#2C77E5')
.size(26)
.label('value', {
style: {
fill: '#222',
fontWeight: 600,
},
offset: 10,
});
this.chart.interaction('element-active');
this.chart.render();
this.first = false;
}
}
}
</script>
<style>
</style>
网友评论