背景
图表展现能力是平台需具备的基础能力,目前echarts是最佳选择。
在早期版本的图表中,不同的图表样式,需要不同的数据格式,需要进行复杂封装才能易于使用。百度官方也意识到这个问题,在echarts 4.0版本提供了dataset属性支持,提供了统一的数据格式,也曾考虑基于这一新特性将常用图表进行封装。
后来,发现了饿了么团队出品的开源组件v-charts,统一提供了一种对前后端都友好的数据格式,只需设置简单的配置项,便可轻松生成常见的图表。
但v-charts停留在了vue2.x版本,vue3.x完全没有动静。
官方自己出了vue-echarts,本文从实战角度介绍下如何与平台进行集成,包括集成方案、具体实现和注意事项等。
技术预研
vue-echarts 官方地址
https://github.com/ecomfe/vue-echarts/blob/HEAD/README.zh-Hans.md
说明过于简单了,如果只看这里的资料,不了解echarts自身的概念和配置,集成和使用时会非常困难,推荐了解以下相关知识。
查看echarts图表官网文档,了解基本概念,如坐标轴、图例、数据集等
https://echarts.apache.org/handbook/zh/concepts/chart-size
查看echarts图表官网文档 配置说明
https://echarts.apache.org/zh/option.html#legend.top
集成目标
echarts提供了种类繁多的图表,大概有40多种大类,详见https://echarts.apache.org/examples/zh/index.html#chart-type-line。
在实际软件系统中,最常见最实用实际就是三大类型图表:折线图、柱状图、饼图。
平台的集成主要目标是实现这三大类图表集成。如某个特定的业务需求使用到了其他类型图表样式,也可以通过直接使用原生的echarts图表组件来实现。
注:对于企业应用而言,图表需求并非只有echarts这一种实现方式。实际复杂的报表需求,特别是管理驾驶舱,往往使用的是类似于帆软这种专门的报表工具。图表工具与报表工具,定位上有差异,但功能又有重叠。图表工具依托后端服务接口,前端进行友好展现,数据的查询、转换都在应用后端完成;而报表功能往往是直连数据库,进行报表模板的开发和部署,数据的查询、转换主要在报表应用端上完成,然后集成到应用系统中,实际的方式机制是不同的。
配置选项
要考虑集成方案,先了解下echarts图表组件现状,对于这三类图表的配置选项要求,具体如下:
饼图
option = {
series: [
{
type: 'pie',
data: [
{
value: 335,
name: '直接访问'
},
{
value: 234,
name: '联盟广告'
},
{
value: 1548,
name: '搜索引擎'
}
]
}
]
};
柱状图
option = {
xAxis: {
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {},
series: [
{
type: 'bar',
data: [23, 24, 18, 25, 27, 28, 25]
}
]
};
折线图
option = {
xAxis: {
data: ['A', 'B', 'C']
},
yAxis: {
},
series: [
{
data: [120, 200, 150],
type: 'line'
}
]
};
配置分析
相同点
图表类型,统一放在series.type属性中
不同点
饼图则没有x轴和y轴的概念,在series.data里配置一个对象数组,name代表类目,value代表值
折线图和柱状图相同,基于直角坐标系,有x轴和y轴,xAxis.data类配置一个一维数组作为类目,series.data里配置一个一维数组作为值
集成方案
实现模式——传统模式VS数据集模式
基于上述分析,可以为饼图、柱状图和折线图各封装出一个组件来,组件内部提供默认设置,将关键属性,如数据data,属性option作为属性暴露,供调用方使用。
这种方式能走得通,但并非最佳方案。在最开始背景部分,提到过echart产品的演进。在早期版本的图表中,不同的图表样式,需要不同的数据格式,需要进行封装才能易于使用。官方也意识到这个问题,在echarts 4.0版本提供了dataset属性支持,提供了统一的数据格式。
使用数据集的优势主要自于将数据与配置分离,使数据可以多组件复用,以下引用官方说明:
数据集(dataset)是专门用来管理数据的组件。虽然每个系列都可以在 series.data 中设置数据,但是从 ECharts4 支持数据集开始,更推荐使用数据集来管理数据。因为这样,数据可以被多个组件复用,也方便进行 “数据和其他配置” 分离的配置风格。毕竟,在运行时,数据是最常改变的,而其他配置大多并不会改变。
在系列中设置数据
如果数据设置在 系列(series) 中,例如:
option = {
xAxis: {
type: 'category',
data: ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie']
},
yAxis: {},
series: [
{
type: 'bar',
name: '2015',
data: [89.3, 92.1, 94.4, 85.4]
},
{
type: 'bar',
name: '2016',
data: [95.8, 89.4, 91.2, 76.9]
},
{
type: 'bar',
name: '2017',
data: [97.7, 83.1, 92.5, 78.1]
}
]
这种方式的优点是,适于对一些特殊的数据结构(如“树”、“图”、超大数据)进行一定的数据类型定制。 但是缺点是,常需要用户先处理数据,把数据分割设置到各个系列(和类目轴)中。此外,不利于多个系列共享一份数据,也不利于基于原始数据进行图表类型、系列的映射安排。
在数据集中设置数据
而数据设置在 数据集(dataset) 中,会有这些好处:
- 能够贴近数据可视化常见思维方式:(I)提供数据,(II)指定数据到视觉的映射,从而形成图表。
- 数据和其他配置可以被分离开来。数据常变,其他配置常不变。分开易于分别管理。
- 数据可以被多个系列或者组件复用,对于大数据量的场景,不必为每个系列创建一份数据。
- 支持更多的数据的常用格式,例如二维数组、对象数组等,一定程度上避免使用者为了数据格式而进行转换。
来源:https://echarts.apache.org/handbook/zh/concepts/dataset/
官方对于数据集的优势已经说得很清楚了,不再赘述,选择数据集模式的优势是显而易见的。
组件封装的必要性
官方的vue-echarts,实际已经对echarts进行了良好的封装,包括提供默认配置、对外暴露属性,以及提供事件和方法。
下面来探讨下二次封装的必要性,平台集成是否还需要再二次封装呢?
如果直接使用vue-echarts组件,则优点是该组件质量比较高,且以后还会持续更新,缺点是需要了解echarts的基本概念和配置信息,遵循echarts的规范和要求,有一定的学习成本。
如果二次封装,可以将echarts的配置信息给封装掉,例如为饼图专门封装一个组件,暴露一个属性data用来接收数据就好了,其他细节一概不管,由平台提供默认实现,缺点在于,将vue-echarts组件的属性、事件、方法再包装一层提供出去,价值和意义不大。
此外,vue-element-plus-admin框架自带的封装组件中,有对vue-echarts组件的二次封装,使用时只需要输入配置option和高度height即可。
考虑到官方vue-echarts自身封装质量高,灵活性和扩展性强,暂不进行封装,以后有了更明确的封装的必要性后再考虑二次封装。
同时,鉴于echart自身提供了数据集模式,以及提供了数据映射功能,因此专门封装前后端交互的vo对象这件事也不需要做了,完全可以复用现有的rest请求,返回实体的对象数组,在echarts中配置数据映射。
具体实现
安装
pnpm install echarts vue-echarts
注意,需要同时安装这两个,而不是只安装vue-echarts就行了。
引入
修改main.js文件,增加echarts的引入和初始化
// echart图表
import "echarts"
import ECharts from "vue-echarts"
// 创建实例
const setupAll = async () => {
const app = createApp(App)
略
// echart图表
app.component('v-chart', ECharts)
app.mount('#app')
}
这里实际采用的全量引入模式,后面再优化,实现仅引入折线图、柱状图和饼图这三大类用到的图表,缩减体积。
使用
在前端项目modules目录下新建一个echart的目录,用于存放示例图表,在其下方创建了三个典型图表。并使用了平台的Portlet功能进行了定义。
可以直接通过拖动来配置为自己的桌面,如下图
最终效果如下:
以下是代码实现,注意使用了数据集的方式,
饼图:用户来源
<template>
<v-chart :option="option" theme="auto" :autoresize="true" style="width: 100%; height: 300px" />
</template>
<script>
export default {
data() {
return {
option: {
dataset: {
source: [
['数量', '来源'],
[335, '直接访问'],
[310, '邮件营销'],
[234, '联盟广告'],
[135, '视频广告'],
[1548, '搜索引擎']
]
},
title: {
show: false
},
grid: {
top: 20,
bottom: 0
},
tooltip: {
trigger: 'item',
formatter: function (params) {
// 只返回第一列数据
return params.data[0] + '(' + params.percent + '%)'
}
},
legend: {
orient: 'horizontal',
top: 'bottom',
left: 'center'
},
series: [
{
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
encode: {
tooltip: [0, 1],
value: 0,
itemName: 1
},
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
}
}
},
methods: {}
}
</script>
<style></style>
官网基于数据集和数据映射的内容介绍比较分散,实际还是需要自己多尝试修改下配置,来确认参数作用,实现最终效果。
注意点有两个地方。
一是数据映射,如下图。value:0代表将数据集dataset中第0列作为数据,itemName: 1代表将数据集dataset中第1列作为维度。映射错了图表很可能就显示残缺或干脆显示白屏。
encode: {
tooltip: [0, 1],
value: 0,
itemName: 1
}
二是鼠标悬停某个区域时,浮动显示进一步信息,默认的配置是
如果想显示占比 ,需要自己重写formater方法,如下图所示
tooltip: {
trigger: 'item',
formatter: function (params) {
// 只返回第一列数据
return params.data[0] + '(' + params.percent + '%)'
}
}
效果如下:
显示效果确实不如官方默认的美观,不过还是可以进一步控制的,这里只是提供一种定制的思路。
这些内容是官网里没提到的,自己摸索,用console.log打印出了params信息,发现有了percent属性,就不用自己去做计算了。
周活跃用户数:柱状图
<template>
<v-chart :option="option" theme="auto" :autoresize="true" style="width: 100%; height: 300px" />
</template>
<script>
export default {
data() {
return {
option: {
dataset: {
source: [
['count', 'week'],
[13253, '周一'],
[34235, '周二'],
[26321, '周三'],
[12340, '周四'],
[24643, '周五'],
[1322, '周六'],
[1324, '周日']
]
},
xAxis: { type: 'category' },
yAxis: {},
series: [
{
type: 'bar',
encode: {
x: 'week',
y: 'count'
}
}
]
}
}
},
methods: {}
}
</script>
<style></style>
注意以下属性必须有
xAxis: { type: ‘category’ },
yAxis: {},
要不然会报一个莫名奇妙的错误uncaught (in promise) Error: xAxis “0” not found
月销售量:折线图
下面实际是一个双折线图
<template>
<v-chart :option="option" theme="auto" :autoresize="true" style="width: 100%; height: 300px" />
</template>
<script>
export default {
data() {
return {
option: {
dataset: {
source: [
['estimate', 'actual', 'month'],
[100, 120, '一月'],
[120, 82, '二月'],
[161, 91, '三月'],
[134, 154, '四月'],
[105, 162, '五月'],
[160, 140, '六月'],
[165, 145, '七月'],
[114, 250, '八月'],
[163, 134, '九月'],
[185, 56, '十月'],
[118, 99, '十一月'],
[123, 123, '十二月']
]
},
xAxis: {
type: 'category'
},
yAxis: {
axisTick: {
show: false
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
padding: [5, 10]
},
legend: {
data: ['预计', '实际'],
top: 20
},
series: [
{
type: 'line',
name: '预计',
smooth: true,
encode: {
x: 'month',
y: 'estimate'
},
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
{
type: 'line',
name: '实际',
smooth: true,
encode: {
x: 'month',
y: 'actual'
},
animationDuration: 2800,
animationEasing: 'quadraticOut'
}
]
}
}
},
methods: {}
}
</script>
<style></style>
总结
从上面具体使用可以看出来,直接使用官方已经封装好的vue-echarts组件还是比较方便的,配置option是复杂多变的,二次封装的意义不大。在此基础上使用其他类型的图表,也很容易。
echarts自身的概念和配置选项不可避免要花点时间去了解和熟悉,总体而言学习成本还好,注意使用数据集模式。
开发平台资料
平台名称:一二三开发平台
简介: 企业级通用开发平台
设计资料:csdn专栏
开源地址:Gitee
开源协议:MIT
开源不易,欢迎收藏、点赞、评论。