背景
在数据大屏中,图表可视化的样式、动画效果能够大大提升用户的视觉体验和交互感受。
VChart 的特效种类繁多,其适配的主题也涵盖了多种风格,从简约现代到复古经典,从科技感十足到自然生态,能够满足不同场景和用户需求。而且,VChart 的样式定制化极其灵活,用户可以根据自身品牌形象和数据特点,对图表的颜色、形状、大小等进行个性化调整,从而打造出独一无二的数据大屏展示。
VChart 已在多个 React 项目中集成并使用,但鲜有 Vue 框架的实践案例。为此我们基于热门开源大屏项目 Go-View 进行拓展,集成 VChart 可视化能力,丰富 Go-View 的功能和表现形式。
GO-View项目
GoView 是一个Vue3搭建的低代码数据可视化开发平台,将图表或页面元素封装为基础组件,无需编写代码即可完成业务需求。 它的技术栈为:Vue3 + TypeScript4 + Vite2 + NaiveUI + ECharts5 +VChart + Axios + Pinia2 + PlopJS。它提供拖拽式组件库与动态数据绑定能力,支持快速搭建交互式数据大屏。其核心功能涵盖多主题适配、实时数据渲染、企业级安全模块,适用于智慧城市、商业智能等场景。
📚 GoView 文档 地址:www.mtruning.club/
纯前端
Demo 地址:vue.mtruning.club/
带后端
Demo 地址:demo.mtruning.club/
GoView 源码
地址:gitee.com/MTrun/go-vi...
功能实现
以新增一个柱状图组件为例
::: warning
务必进行的测试:
- 右侧属性响应式测试
- 数据->动态数据更新测试
- 使用 mock 数据,更新时间设置为 5S,点击预览查看 5S 后图表是否进行了更新
- 打包编译测试,编译会报 TS 错误,请及时修改.注意: 开发环境并未做 tree-shaking 处理,以下按需导入等同于 import VChart from '@visactor/vchart'全量导入。但当打包编译时将会开启 tree-shaking,如缺少必要组件导入,项目运行将会报错!注册逻辑参考: www.visactor.io/vchart/guid...
:::
- 首先在
packages
的文件夹里新增基础配置文件
路径 | 功能 |
---|---|
packages/index | 所有图表导出,图表动态加载方法等 |
packages/index.d | 类型定义 |
packages/public | 公共数据类,方法等 |
packages/chartConfiguration | 图表基础配置 |
packages/components/Charts | 图表模块 |
packages/components/VCharts | VChart 图表模块 |
packages/components/Informations | 信息模块 |
packages/components/Tables | 表格模块 |
packages/components/Decorates | 装饰模块 |
选择在 packages/components/VChart/Bars
下创建 VChartBarCommon
文件夹
- 在文件夹内创建对应的文件
index.ts
、index.vue
、config.ts
、config.vue
文件 | 功能 |
---|---|
index.ts | 图表声明文件 |
index.vue | 展示渲染文件 |
config.ts | 数据相关文件 |
config.vue | 设置项内容 |
data.json | 静态数据(可无) |
index.ts
内容如下:
javascript
// 公共类型声明
import {
ConfigType,
PackagesCategoryEnum,
ChartFrameEnum,
} from "@/packages/index.d";
// 当前[信息模块]分类声明
import { ChatCategoryEnum, ChatCategoryEnumName } from "../../index.d";
export const VChartBarCommonConfig: ConfigType = {
// 唯一key,注意!!!文件夹名称需要修改成与当前组件一致!!!
key: "VChartBarCommon",
// 图表组件渲染 Components 格式: V + key
chartKey: "VVChartBarCommon",
// 配置组件渲染 Components 格式: VC + key
conKey: "VCVChartBarCommon",
// 名称
title: "VChart并列柱状图",
// 子分类目录
category: ChatCategoryEnum.BAR,
// 子分类目录
categoryName: ChatCategoryEnumName.BAR,
// 包分类
package: PackagesCategoryEnum.VCHART,
chartFrame: ChartFrameEnum.VCHART,
// 图片 (注意!图片存放的路径必须在 src/assets/images/chart/包分类名称/*)
// 文件夹名称需要和包分类名称一致: PackagesCategoryEnum.VCHART
image: "bar_x.png",
};
:::warning 注意!
v1.1.9 / v2.1.6
版本以下,图片需要直接引入。但是开发环境生成的组件,在生产环境的层级展示中图片会有问题。
:::
使用方式如下:
arduino
// 展示图片
import image from "@/assets/images/chart/vchart/bar_x.png";
export const VChartBarCommonConfig: ConfigType = {
// .....和上面一致
// 图片
image: image,
};
data.json
内容如下:
json
{
"values": [
{ "type": "Autocracies", "year": "1930", "value": 129 },
{ "type": "Autocracies", "year": "1940", "value": 133 }
// ...
]
}
config.ts
内容如下,在创建新图表时会执行 new Config()
typescript
// 公共类型和方法
import { vChartOptionPrefixHandle, PublicConfigClass } from "@/packages/public";
// 公共类型
import { CreateComponentType } from "@/packages/index.d";
// 获取上面的 index 配置内容
import { VChartBarCommonConfig } from "./index";
// 深拷贝
import cloneDeep from "lodash/cloneDeep";
// 默认数据
import data from "./data.json";
// 图表公共主题配置
import axisThemeJson from "@/settings/vchartThemes/axis.theme.json";
// 图表配置的类型定义
import { IBarOption } from "../../index.d";
// 从VCharts 的默认配置项里取出需要的部分,详见 `src/settings/chartThemes/index`
export const includes = ["legends", "tooltip"];
export const option = {
// 图表配置
type: "bar",
dataset: data,
stack: true,
xField: ["year", "type"],
yField: ["value"],
seriesField: "type",
// 业务配置(后续会被转换为图表spec)
category: VChartBarCommonConfig.category,
xAxis: {
name: "x轴",
...axisThemeJson,
grid: {
...axisThemeJson.grid,
visible: false,
},
},
yAxis: {
name: "y轴",
...axisThemeJson,
grid: {
...axisThemeJson.grid,
style: {
...axisThemeJson.grid.style,
lineDash: [3, 3],
},
},
},
};
// 柱状图类
export default class Config
extends PublicConfigClass
implements CreateComponentType
{
public key = VChartBarCommonConfig.key;
public chartConfig = cloneDeep(VChartBarCommonConfig);
// 进行样式合并
public option = vChartOptionPrefixHandle(option, includes);
}
index.vue
内容如下:
xml
<template>
<GoVChart ref="vChartRef" :option="chartConfig.option"> </GoVChart>
</template>
<script setup lang="ts">
import { PropType } from "vue";
import { useChartEditStore } from "@/store/modules/chartEditStore/chartEditStore";
import { GoVChart } from "@/components/GoVChart";
import { useChartDataFetch } from "@/hooks";
import config from "./config";
const props = defineProps({
chartConfig: {
type: Object as PropType<config>,
required: true,
},
});
const { vChartRef } = useChartDataFetch(
props.chartConfig,
useChartEditStore,
(newData: any) => {
props.chartConfig.option.dataset = newData;
}
);
</script>
config.vue
内容如下:
xml
<template>
<!-- vCharts 全局设置 -->
<VChartGlobalSetting :optionData="optionData"></VChartGlobalSetting>
<Axis :axis="optionData.xAxis"></Axis>
<Axis :axis="optionData.yAxis"></Axis>
</template>
<script setup lang="ts">
import { PropType } from "vue";
import {
VChartGlobalSetting,
Axis,
} from "@/components/Pages/VChartItemSetting";
import { vChartGlobalThemeJsonType } from "@/settings/vchartThemes/index";
defineProps({
optionData: {
type: Object as PropType<vChartGlobalThemeJsonType>,
required: true,
},
});
</script>
- 然后把图表组件在
src\packages\components\VChart\Bars\index.ts
中进行导出
javascript
import { VChartBarCommonConfig } from "./VChartBarCommon/index";
import { VChartBarStackConfig } from "./VChartBarStack/index";
// 这里的顺序决定着最终的展示顺序
export default [VChartBarCommonConfig, VChartBarStackConfig];
注意在 src\packages\components\VChart\index.ts
也有一个导出,这里是导出 VChart
模块的所有组件
javascript
import Bars from "./Bars";
export const ChartList = [...Bars];
- 在
src\components\GoVChart\transformProps\bars.ts
将业务配置转换为可供 VChart 绘制的标准 spec
ini
import { cloneDeep } from "lodash";
export default (chartProps: any) => {
// 将业务配置拷贝出来处理, 避免影响原配置
const spec = cloneDeep(chartProps);
// 图表类型仅供索引到对应图表spec转换逻辑使用,。在VChart配置中, type即可识别图表类型
delete spec.category;
// tooltip spec 转换
const keyFill = spec.tooltip.style.keyLabel.fill;
const valueFill = spec.tooltip.style.valueLabel.fill;
const titleFill = spec.tooltip.style.titleLabel.keyFill;
delete spec.tooltip.style.keyLabel.fill;
delete spec.tooltip.style.valueLabel.fill;
delete spec.tooltip.style.titleLabel.keyFill;
spec.tooltip.style.keyLabel.fontColor = keyFill;
spec.tooltip.style.valueLabel.fontColor = valueFill;
spec.tooltip.style.titleLabel.fontColor = titleFill;
// 轴spec 转换
const { name: xAxisName, ...restXAxisProps } = chartProps.xAxis;
const { name: yAxisName, ...restYAxisProps } = chartProps.yAxis;
spec.axes = [
{
orient: "bottom",
...restXAxisProps,
// paddingInner: 0.5
},
{
orient: "left",
...restYAxisProps,
},
];
// 去掉无用业务配置
delete spec.xAxis;
delete spec.yAxis;
// console.log('spec-bar-transform', spec)
// 返回VChart可识别的标准spec
return spec;
};
- 在
src\components\GoVChart\transformProps\index.ts
进行导出
typescript
import {
ChatCategoryEnum,
IOption,
} from "@/packages/components/VChart/index.d";
import bars from "./bars";
export const transformHandler: {
[key: string]: (args: IOption) => any;
} = {
// 业务配置中的category用于索引到对应的转换逻辑
[ChatCategoryEnum.BAR]: bars,
// todo: more charts handler
};
-
在
src/components/GoVChart/register.ts
中执行图表注册逻辑. -
开发环境并未做 tree-shaking 处理,以下按需导入等同于
import VChart from '@visactor/vchart'
全量导入。但需注意,当打包编译时将会开启 tree-shaking,如缺少必要组件导入,项目运行将会报错!
javascript
import { VChart } from "@visactor/vchart/esm/core";
import { registerBarChart } from "@visactor/vchart/esm/chart";
import {
registerTooltip,
registerCartesianCrossHair,
registerDiscreteLegend,
registerLabel,
} from "@visactor/vchart/esm/component";
import { registerDomTooltipHandler } from "@visactor/vchart/esm/plugin/components";
import { registerAnimate } from "@visactor/vchart";
// 不同图表类型需要注册什么样的组件可以参考: https://www.visactor.io/vchart/guide/tutorial_docs/Load_on_Demand
export const registerChartsAndComponents = () => {
VChart.useRegisters([
// 图表
registerBarChart,
// 组件
registerTooltip,
registerDomTooltipHandler,
registerCartesianCrossHair,
registerDiscreteLegend,
registerLabel,
// 动画
registerAnimate,
]);
};
此时页面图表中将出现【柱状图】组件,试试把它拖拽到页面进行测试吧~
最终效果
欢迎交流
最后,我们诚挚的欢迎所有对数据可视化感兴趣的朋友参与进来,参与 VisActor 的开源建设:
VChart :VChart 官网、VChart Github(欢迎 Star)
VTable :VTable 官网、VTable Github(欢迎 Star)
VMind :VMind 官网、VMind Github(欢迎 Star)
官方网站:www.visactor.io/ 或 www.viactor.com
Discord:discord.gg/3wPyxVyH6m
飞书群(外网):打开链接扫码
微信公众号:打开链接扫码
github:github.com/VisActor