1 可视化图表分几个层次,底层图表库
- echarts
- g2
- d3
- chartjs 使用canvas绘制
- nvd3
2 基于可视化图表封装的可视化组件
React系的
- G2Plot
- BizCharts
- XRender的ChartRender
Vue系的
- VCharts
计划
- 基本部分的编写,各方案实现需求1
- BI配置平台如何实现的?
- 三部分组件的封装 7:30 ~ 9:00
- 最终的组件配置方案
- 三个图标部分解释,以及需求2的实现
- BI平台如何配置的先删除掉?
- 最后的总结
- 本质的思考?
先了解数据是什么样
数据分析中两个重要的概念,指标(metrics)和维度(dimension)
- 指标,一般指可量化的数据,是进行统计后的结果
- 维度,一个分类值,事物的某种特征
以一个分析网站PV和UV的案例来看
date和page两个就是维度,日期和发生的页面
pv和uv就是指标,是根据制定条件聚合计算后的统计结果
下面是服务端返回的数据
[{
date: "2021-07-21",
page: "home",
pv: 200,
uv: 100
},
{
date: "2021-07-21",
page: "detail",
pv: 100,
uv: 50
},
{
date: "2021-07-22",
page: "home",
pv: 300,
uv: 120,
}
{
date: "2021-07-22",
page: "detail",
pv: 180,
uv: 60,
}]
以一个需求看各图表如何配置
需求1,x轴是日期,y周是pv数值,折线1是home的,折线2是detail的。即多折线图是按某一维度展开。
需求2,x周是日期,y周是数值,折线1是pv,折线2是uv。即多折线图是多个维度值。
使用Echarts
需要填入这些数据
- 使用xAxis来描述X轴,data填入x轴的数据
- 使用series来表述每条线,type写上图表类型,data填入数据
- legend描述上顶部legend的内容
{
legend: {
data: ['home', 'detail']
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['2021-07-21', '2021-07-22']
},
yAxis: {
type: 'value'
},
series: [
{
name: 'home',
type: 'line',
stack: '总量',
data: [200, 300]
},
{
name: 'detail',
type: 'line',
stack: '总量',
data: [100, 180]
},
}
优点
- 学习成本低,只要记住series代表一条线
- API文档非常详细和易用
- 生态,使用者众多,一般问题搜搜都有各种解法
存在的问题
- 即需要将服务端数据进行转换,转换为echarts这样需要的数据格式
- 即使echarts支持了dataset,但最终还是每个series一条线的思维,在多指标和多维度时不同的处理方式,有一定的转换成本。
- 数据信息的丢失
- 经过数据转换,原始的一条数据记录变成了数字
- 如果一条记录中还有其它字段,在tooltip时想要展示更多信息,需要先找到原始数据,再进行提示。
使用g2
const chart = new Chart({
container: 'container',
autoFit: true,
height: 500,
});
// 传入数据
chart.data(data);
// 映射到图表
chart
.line()
.position('date*pv')
.color('page')
.shape('smooth');
chart.render();
优点
- 如果有进一步定制能力,使用了图表garmmar语法,echarts无法满足,可以较快的进行创造。
- garmmar语法,简洁易于推理,在坐标轴画点,然后上色就成了不同的线。
存在的问题
- 使用的garmmar语法,如果常用图表一般都会进行开发封装,还是会封装成一般的API
使用G2Plot
需求1 多指标单维度
const line = new Line('container', {
data,
xField: 'date',
yField: 'pv',
seriesField: 'page'
}
需求2 单维度多指标
- 需要先转换数据
如果是
{ date: “2021-07-22”, pv: 300, uv: 120,
}
转换为
{
date: “2021-07-22”, type: ‘pv’, value: ‘300’ }, { date: “2021-07-22”,
type: 'uv',
value: '300'
}
// 转换数据
const transformedData = transform(data)
// 渲染图表
const line = new Line('container', {
transformedData,
xField: 'date',
yField: 'value',
seriesField: 'type'
}
总结
- 在多指标时需要进行数据转换
- 不同图形时,数据参数差异比较多,记忆成本 (这里没展开介绍)
使用BizCharts的ChartRender
<Line
meta={[
{ id: 'date', name: '日期', isDim: true },
{ id: 'page', name: '页面', isDim: true },
{ id: 'pv', name: '页面访问数' },
}],
data=data
/>
优点
- 参数非常简洁,背后自动转换
只需要传入说明是否是dimension,line中如果两个dimension,则一个会自动作为分类的线。
如果两个指标,则会自动将不同指标作为多条线
缺点
- 暂时只封装了折线图,柱状图,不知道其他图形的适用性如何
总结对比
设计思想 | 问题和缺点 | |
---|---|---|
Echarts | ||
g2 | 通过 | |
G2Plot | 自动数据映射,指明x轴y轴,指明分类维度 | - 需要记忆的 |
ChartRender | 自动数据映射,指明维度和指标,自动帮助选择了x,y轴,以及分类维度 | 这个新加入这 |
需求2对比
参考各BI平台如何配置的
对比几个常见的商业BI平台
- finebi
- tableau
- powerbi
案例1 两个维度 | 案例2 两个指标 | |
---|---|---|
finebi | - 横轴 date - 纵轴 pv - 颜色 (page) |
- 横轴 date - 纵轴 pv, uv |
tableau | - 横轴 date - 纵轴 pv - 颜色 (page) |
- |
|
| powerbi |
- 轴(axis) -> date
- 图例(legend) -> page
- 值(value) -> pv
|
- 轴(axis) date
- 值 pv, uv
|
同时在其他几个不同图形(条形图,柱状图)时,powerbi都是用轴和值来表述,而不是用坐标系的横轴和纵轴来进行表述。
所以综合上,从个人体验讲,powerbi的在不同图形时,描述的通用性比较强,也比较容易的理解和推理各配置。
最终我们的封装方案
我们基于echarts,因为成熟度比较高,再进行一定的封装,不需要用户做数据的转换操作。映射参数借鉴了PowerBI的表达方式。
下面列出不同图形的传入
同时还暴露了config参数,如果需要配置一些echarts的配置,此参数可以进行覆盖。
更进一步封装
一个图表的呈现,还有哪几步?
主要是三大部分
- api请求数据
- 可能和容器内或容器外筛选功能关联
- lazyload,未展示时,不请求和展示
- 并发控制,同时请求的不能超过5个 (大量并发服务器计算压力)
- 图表展示卡片容器
- 筛选空间,时间筛选等
- 对比功能,对比昨天,对比上周
- 功能按钮,筛选
- 图表的绘制
- 不同种类的图形
因此,设计了三个组件,保证职责的分离,ChartContainer和ChartCard通过context来进行提供和消费
ChartContainer控制api请求和数据
- lazyload,以及监听参数变更请求数据
- 通过context,提供了相应的数据和api
- 数据,loading,data
- api,refresh,switchCompare
ChartCard负责图表卡片,以及里面的功能按钮
- 通过context,消费chartContainer提供的api,在各功能按钮点击时调用
Line图表组件,
即图表的展示,为了通用性,保证低耦合,data数据通过 chart-container
提供的 slot-scope
暴露的data参数传入。
下面是组合代码的展示
<chart-container
api="api/pageView"
:params="params"
>
<template v-slot:default="{ data }">
<chart-card>
<my-line
:data="data"
></my-line>
</chart-card>
</template>
</chart-container>
图表数据映射支持
- chartjs中的数据parsing
https://www.chartjs.org/docs/latest/general/data-structures.html
echarts中的dataset
g2中直接映射的描述
对数据 & 图表本质的思考
总结
在设计封装时,需要考虑自己是否了解所有需求,所有的场景,否则设计就会有问题。
如刚开始未考虑到 单维度多指标需求
,即指标有 pv
, uv
两个