作者:千梦凯
前言
古茗加盟商在经营店铺的过程中,需要一款可视化的工具来将门店的经营情况。通过图表将数据呈现得更加直观、易懂;并且可以根据数据趋势,分析门店经营情况。
目前古茗主要通过钉钉小程序来辅助加盟商经营,并且开发使用Taro+React的方式进行开发小程序,本文将介绍如何使用Taro在钉钉小程序中实现数据图表化展示。
可视化图表库技术选型
目前市面上比较流行的可视化工具库有
- ECharts:一个基于 JavaScript 的开源可视化图表库官网地址
- Chart.js:基于HTML5的简单易用的JavaScript图表库 官方网站
- D3.js:一个数据驱动的可视化库,通过使用HTML、SVG和CSS来操作数据,创造出交互式和动态的图表官方网站
- AntV:蚂蚁企业级数据可视化解决方案官网地址
在wbe端我们使用任何一个库都可以实现可视化展示。不过针对钉钉小程序,我们要根据一下几个关键字来进行筛选使用的图表库(移动端、小程序、手势交互)
- Echarts上面有丰富的图表库,但是代码体积过大。全量代码将近1000k,选择常用功能也要500k左右,在小程序主包只有2m的情况下还是占用了太多的内容。
- Chart.js 依赖于DOM API,而钉钉小程序的环境并不提供完整的DOM API。所以无法直接使用
- D3.js是通过使用SVG来支持图表,但是目前小程序不支持使用SVG,所以无法在小程序中使用
- Antv/F2 F2 是一个专注于移动端,面向常规统计图表,开箱即用的可视化引擎,完美支持 H5 环境同时兼容多种环境(Node, 小程序)
对比之下,F2图表方案更适合在小程序中使用。
由于我们在接入图表库时,4.x版本尚未更新,所以第一版本使用了3.x版本。在后续F2的更新迭代中,由于图表库是在主包中展示,考虑到文件大小的原因,最终使用了4.x版本。
如果是初次接入,推荐直接使用最新版本,功能更加强大。
在Taro+React中使用F2 4.x
在查看F2的文档时,发现文档中有React和小程序的接入,并没有教程说明如何使用Taro的接入。既然可以在小程序和React工程中使用,理论上在Taro+React工程中也可以使用。说干就干,让我们先跟着文档上面的React教程进行接入。
创建Taro+React工程
根据Taro文档,创建React工程,并且新增钉钉小程序编译选项文档教程
安装F2相关依赖
1 | PowerShell复制代码npm install @antv/f2 --save |
在index文件中复制F2官网Demo
1 | typescript复制代码import Canvas from '@antv/f2-react'; |
执行代码
通过上述代码,执行后,钉钉小程序控制台报错
创建Canvas绘图上下文
查看错误代码,发现错误文件为@antv/f2-react报错。通过查看代码,发现钉钉小程序是通过调用dd.createCanvasContext(canvasId) 创建canvas绘图上下文,调整相关代码
1 | typescript复制代码 |
调整代码后,控制台不报错了,并且也渲染出来图表的,不过图表渲染的有点奇怪,只有左上角一点点图形
通过查看F2源码,发现在初始化图表时,需要获取Canvas的宽高。如果外部没有传入宽高,代码中通过DOM API获取元素宽高,但是小程序不支持该方式,所以显示图形异常。以下为相关代码
获取Canvas宽高
1 | scala复制代码class Canvas extends EventEmit { |
初始化设置canvas宽高
既然无法默认获取元素宽高,那我们可以使用小程序提供获取元素宽高的方式,来手动的获取元素的宽高,并且赋值给Props对象
1 | scala复制代码// 调整f2-canvas相关代码 |
设置宽高后,柱状图可以正常显示
虽然柱状图正常显示出来了,不过图表很模糊,像是带了老花镜看似的。通过查看F2文档,发现可以通过配置pixelRatio来设置图表清晰度。并且钉钉小程序可以通过getSystemInfoSync获取设备的分辨率
pixelRatio方案设置
1 | scala复制代码// 调整f2-canvas相关代码 |
设置完成之后,查看柱状图,直接不显示数据了。
通过查找钉钉小程序API,没有找到任何关于Canvas精确度的问题。不过最终通过查看钉钉小程序老大哥支付宝小程序的开发文档,发现了相关内容 支付宝小程序文档-canvas画布问题,通过给Canvas元素设置高分辨率宽高来解决
1 | kotlin复制代码// 调整f2-canvas相关代码 |
设置完成之后,图表就可以高清展示了
notice:设置Canvas宽高后,TS会报错,width属性不存在。是因为Taro中没有定义Canvas的width和height属性。可以手动添加一下ts文件
1 | typescript复制代码declare module '@tarojs/components' { |
抹平context差异
图表虽然可以正常展示了,不过并没有坐标信息。当我们尝试给图标添加坐标信息时,发现页面代码报错会报错
1 | typescript复制代码 <F2Canvas id='wrap'> |
通过查看在小程序中使用F2相关文档,发现F2 是基于 CanvasRenderingContext2D 的标准接口绘制的,但是小程序中给的 context 对象不是标准的 CanvasRenderingContext2D , 所以需要将context对象进行封装兼容处理,详情可见: github.com/antvis/f2-c…, 其他小程序也可以按同样的思路封装。继续修改相关代码,抹平小程序context差异。
1 | scala复制代码import { my } from '@antv/f2-context' |
当我们完成所有操作后,图表和坐标信息就可以完整的展示出来了
事件传递
图表已经可以正常展示,不过当我们使用Tooltip组件时,我们所有的事件都没有作用。
通过查看f-my代码时,我们需要当触发Canvas容器组件事件时,触发图表组件事件
1 | typescript复制代码 |
事件传递后,可以正常显示文案提示
小结
本章节在Taro+React中接入F2的过程中遇到了不少问题。通过查看React与小程序的接入方式,一步一步的解决下面的问题
- 在小程序中Canvas的上下文获取方式和web不一致
- 每次执行代码时需要手动获取Canvas的宽高(无法通过DOM API获取)
- 小程序模糊问题(pixelRatio的设置)
- 小程序中Canvas的context不是标准的CanvasRenderingContext2D对象,需要对齐添加补丁。目前查询支付宝小程序文档,发现最新版本已经调整为标准对象了,不过钉钉小程序目前还不支持
- 小程序事件需要显式定义,并且传递给图表库
目前已经有人封装好了对应的接入代码,我们可以直接在github中查看使用
Taro+React+F2
实战使用
当我们完成上述代码后,就可以正常的根据F2的官网示例在钉钉小程序中使用图表了。不过部分功能需要额外开发
自定义Tooltip
目前F2中默认的Tooltip提示都是在图表顶部显示,并且展示上面只能设置部分属性,不太满足这边的UI规范。好在Tooltip提供了自定义实现的方式,让我们可以自定义显示Tooltip提示。目前古茗通过使用View标签,并且绝对定位的方式来显示对应的文本信息
自定义配置方式
通过设置属性custom,F2不会显示默认Tooltip。通过onChange获取当前的选中的元素信息,可以拿到对应的位置信息与数据信息。从而可以自定义显示对应文本
1 | ini复制代码// 自定义配置 |
View标签位置获取
1 | ini复制代码import { View } from '@tarojs/components'; |
实现效果
使用过程中存在的“坑”
示例
横坐标为0,无法触发Tooltip事件
当Axis坐标轴的值为0时,Tooltip点击事件不能点击执行
折线图反转后表现不一致
折线图反转后,空值直接链接了。没有截断处理
解决方案
一般上解决三方库中的问题
- 对于不在维护的库,通过patch的方式进行处理
- 升级库版本解决
- 对于class组件,可以通过本地覆盖式更新代码
目前F2上面所有的组件都是class组件,所以可以通过继承或者修改原型链的方式来解决上述相关问题。
因为上面两个问题属于明显的bug,在我们这边采用修改原型链上面的方法来解决bug。
横坐标为0问题分析
因为是Tooltip的show方法没有执行,通过寻找代码,找到最终原因为判断date值时,没有处理0导致的。5.x已优化该问题
Tooltip中withTooltip的show方法
1 | arduino复制代码 show(point, _ev?) { |
Chart的getSnapRecords方法
1 | kotlin复制代码 getSnapRecords(point, inCoordRange?) { |
Line的getSnapRecords方法继承Geometry中的getSnapRecords
1 | arduino复制代码 getSnapRecords(point, inCoordRange?): any[] { |
解决方案,重写Geometry的getSnapRecords方法
1 | javascript复制代码const resetGeometryGetSnapRecords = () => { |
折线图反转后表现不一致
该问题为折线图展示的线不一致问题。第一个图为两条线,第二个图为一条线。查看Line相关代码,发现折线图在render的时候通过this.mapping()获取了对应的记录点
折线图没有处理坐标反转时的坐标
1 | javascript复制代码import { jsx } from '../../jsx'; |
解决方案,重写Line的splitNulls方法
1 | ini复制代码 Line.prototype.splitNulls = function (points, connectNulls) { |
总结
以上我们通过分析世面上的图表库,选择了在钉钉小程序中使用F2图表库进行开发。因为小程序不支持DOM相关API和Canvas不是标准的CanvasRenderingContext2D对象,接入过程中踩了不少的坑,对新人不太友好。不过最后还是根据官方的接入文档完成了小程序的接入。强烈建议F2官网可以在官网中加入Taro的接入,降低使用门槛
小茗推荐
最后
关注公众号「Goodme前端团队」,获取更多干货实践,欢迎交流分享。
本文转载自: 掘金