写点什么

基于 f2 从零实现移动端可视化编辑器

用户头像
徐小夕
关注
发布于: 2020 年 11 月 14 日
基于f2从零实现移动端可视化编辑器

前言

笔者之前花了大量的时间在思考如何设计和实现 H5 页面可视化编辑器 H5-Dooring,从第一个版本到现在经历了很多次版本迭代和优化,也收到了很多宝贵的建议,目前刚好完成了移动端数据可视化的基本设计和落地方案,在这里特地总结和复盘一下。

我们先来看看实现的基本预览图:


你将收获

  • 基于 antv/f2 实现可视化图形组件的封装

  • 如何设计表格编辑器并集成到 antd 的 Form 中

  • 数据可视化组件的 schema 约定

  • 利用 js-xlsx 解析 Excel 文件并导入到 Table 中作为可视化组件的数据源

正文

在开始正式实现之前笔者先对 H5 数据可视化做一个基本的介绍,方便大家理解其价值。

1. H5 数据可视化方案的应用场景

随着人工智能和大数据的快速发展,数据可视化设计在移动端的应用越来越多,主要体现在数据图表,也就是我们常见的柱状图折线图条形图雷达图等。它们能很形象的展示不同产品或者某类特征的变化趋势,从而为我们决策提供依据。比如说我们常见的性格测试雷达图,各类金融 app 比较爱玩的某某 g 票的趋势预测折线图,运营人比较喜欢用的漏斗模型等,几乎任何领域都有自己的可视化应用。如下图几个例子:




所以为了满足企业对移动端场景下的可视化需求,能设计一款针对移动端的傻瓜式可视化搭建平台是非常有实际意义的,目前也有很多公司在做,在商业智能领域也有不错的应用。接下来笔者就来带大家一起实现一个这样的 H5 数据可视化搭建平台。

2. H5 数据可视化设计平台的实现方式

目前市面上已有的比较流行的可视化库有 echartantvD3.js 等,针对于移动端而言,笔者还是觉得 antv/f2 更加适合,其官网介绍如下:

F2 是一个专注于移动,开箱即用的可视化解决方案,完美支持 H5 环境同时兼容多种环境(Node, 小程序,Weex),完备的图形语法理论,满足你的各种可视化需求,专业的移动设计指引为你带来最佳的移动端图表体验。

我们就暂且相信它官网的描述,接下来的技术实现笔者也会基于 f2 做可视化组件的二次封装。

2.1 需求设计

笔者在开发产品之前的一贯风格就是先要理清需求,只有在需求确定之后我们才能做更加合适的技术选型和方案,所以笔者在此带大家分析一下移动端可视化编辑器的需求设计。

上图为一个可视化组件编辑器的基本模型,组成结构大致为:

  • 图表组件

  • 数据源

  • 属性编辑器(组件标题,颜色,对齐等属性)

所以说我们大致可以抽象为如下原型:


组件列表为我们提供选择不同组件的能力,画布区域主要用来拖拽图形和调整图形位置,大小,编辑器用来定制图形的“形状”和数据源导入。在了解基本的需求之后我们来进行接下来的开发工作。

2.2 基于 antv/f2 实现可视化图形组件的封装

由于市场上暂时没有比较成熟的基于 f2 react 组件等封装, 所以这里笔者对其做一个简单的二次封装来实现我们的组件定制的需求。对于组件列表,为了提高加载性能,笔者用图片占位符代替。数据传递方式和H5-Dooring已有组件的拖拽一致,这里就不一一介绍了。

在开发组件之前我们先安装一下 f2:

yarn add antv/f2复制代码
复制代码

为了进一步降低移动端代码体积和提高加载性能,我们在引入组件时可以按需引入:

// 引入核心包const Core = require('@antv/f2/lib/core');require('@antv/f2/lib/geom/line'); // 只加载折线图require('@antv/f2/lib/geom/area'); // 只加载面积图复制代码
复制代码

按需引入的方式官网上有详细的说明,感兴趣的可以学习了解一下。

在上面的需求分析中我们大致了解了可视化组件需要设置的属性,这里我们先整理一下以便接下来对可视化组件的封装:

我们来看看 Chart 组件的实现:

// components/Chartimport { Chart } from '@antv/f2';import React, { memo, PropsWithChildren, useEffect, useRef } from 'react';import ChartImg from '@/assets/chart.png';
import styles from './index.less';
type DataItem = { name: string; value: number;};
interface XChartProps { isTpl: boolean; title: string; color: string; size: number; paddingTop: number; data: Array<DataItem>;}
const XChart = (props: PropsWithChildren<XChartProps>) => { const { isTpl, data, color, size, paddingTop, title } = props; const chartRef = useRef(null); useEffect(() => { if (!isTpl) { const chart = new Chart({ el: chartRef.current || undefined, pixelRatio: window.devicePixelRatio, // 指定分辨率 });
// step 2: 处理数据 const dataX = data.map(item => ({ ...item, value: Number(item.value) }));
// Step 2: 载入数据源 chart.source(dataX);
// Step 3:创建图形语法,绘制柱状图,由 genre 和 sold 两个属性决定图形位置,genre 映射至 x 轴,sold 映射至 y 轴 chart .interval() .position('name*value') .color('name');
// Step 4: 渲染图表 chart.render(); } }, []); return ( <div className={styles.chartWrap}> <div className={styles.chartTitle} style={{ color, fontSize: size, paddingTop }}> {title} </div> {isTpl ? <img src={ChartImg} alt="dooring chart" /> : <canvas ref={chartRef}></canvas>} </div> );};
export default memo(XChart);复制代码
复制代码

以上 Chart 组件就基本封装完毕,如果有更多定制化需求,也可以自行添加。代码中我们采用 typescript React Hooks 开发,为了对组件进行做优化,我们用了 memo,如果对这些技术点不熟悉的,稍后可以移步我的 react hooks typescript 相关的文章学习。

以上只是完成了基本的可视化组件的封装,接下来的重点是实现可视化组件和表单编辑器之间的联动。

2.3 设计表格编辑器并集成到 antd 的 Form 中

表格编辑器的实现我们主要基于 antd Table 组件来实现,当我们点击数据源的时候,会弹出表格编辑器,我们先来看看效果:

我们可以直接对数据源进行编辑,比如修改数据,删除数据,添加数据,也即是 CURD 的那套流程。并且支持导入 excel 数据,这块笔者将在下一章节来实现。

可编辑表格实现原理就是在表格中加入状态,分为查看模式和编辑模式,编辑模式采用 input 框,在失焦时进行保存/切换查看状态。添加行的逻辑主要是动态插入一条数据,这块实现也比较简单,具体实现感兴趣的朋友可参考我的源码

部分代码参考如下:

// 添加行handleAdd = () => {  const { count, dataSource } = this.state;  const newData = {    key: count,    name: `dooring ${count}`,    value: 32,  };  const newDataSource = [...dataSource, newData];  this.setState({    dataSource: newDataSource,    count: count + 1,  });  this.props.onChange && this.props.onChange(newDataSource);};
// 保存行数据handleSave = row => { const newData = [...this.state.dataSource]; const index = newData.findIndex(item => row.key === item.key); const item = newData[index]; newData.splice(index, 1, { ...item, ...row, }); this.setState({ dataSource: newData }); this.props.onChange && this.props.onChange(newData);};复制代码
复制代码

上面代码的 this.props.onChange 主要是为了 antd Form 能接受到变化,使 Table Editor 成为 Form 的“受控组件”。

2.4 利用 js-xlsx 解析 Excel 文件并导入到 Table 中作为可视化组件的数据源

对于上面介绍的数据源录入,我们有两种模式:手动录入文件导入。设计文件导入主要是为了更好的用户体验,这里为了实现该功能我们可以采用社区比较火的 js-xlsx,一款专业的解析 excel 数据的插件,而且可以输出多种数据类型。

我们先来安装一下:

 npm install xlsx复制代码
复制代码

读取 excel 文件数据代码如下:

// 读取本地excel文件function readLocalFile(file, callback) {	let reader = new FileReader();	reader.onload = function(e) {		let data = e.target.result;		let formData = XLSX.read(data, {type: 'binary'});		if(callback) callback(formData);	};	reader.readAsBinaryString(file);}复制代码
复制代码

有了以上代码,我们只需要在导入 excel 的按钮上绑定事件并解析数据即可实现导入功能。大家可以尝试一下。

以上就基本实现了我们的真个体系设计,后面的雷达图,折线图等实现原理也类似。我们看看用 H5-Dooring 配置出的几个案例:


当然大家也可以在 H5-Dooring 定制自己的 H5 数据可视化面板

3. 总结

以上教程笔者已经集成到 H5-Dooring 中,对于一些更复杂的交互功能,通过合理的设计也是可以实现的,大家可以自行探索研究。

github 地址:H5在线编辑器H5-Dooring

最后

如果想学习更多 H5 游戏, webpack,node,gulp,css3,javascript,nodeJS,canvas 数据可视化等前端知识和实战,欢迎在《趣谈前端》一起学习讨论,共同探索前端的边界。


发布于: 2020 年 11 月 14 日阅读数: 633
用户头像

徐小夕

关注

前端架构师,致力于前端工程化,可视化 2020.08.08 加入

公众号《趣谈前端》.喜欢coding, 开源, 擅长领域react, vue, nodejs, 小程序, 小游戏, 热爱旅游, 健身, 微信Mr_xuxiaoxi

评论

发布
暂无评论
基于f2从零实现移动端可视化编辑器