小编语:本文是小编本周的工作总结,文中观点只代表个人观点,由于个人能力以及看法的局限,文中定有描述不准确之处,望各位读者多多包涵并指出。
按照惯例,首先欢迎一波 star:

前提

小程序是一种新的应用形态,微信之父张小龙是这样描述小程序的:
小程序是一个不需要下载安装就可使用的应用,它实现了应用触手可及的梦想,用户扫一扫或者搜一下即可打开应用。也体现了用完即走的理念,用户不用关心是否安装太多应用的问题。应用将无处不在,随时可用,但又无需安装卸载。
自微信小程序推出之后,各大互联网公司以及手机厂商也纷纷入局,其中蚂蚁金服上线推出了支付宝小程序,作为轻应用鼻祖的百度也在近日于手机客户端悄然上线一款名为“优信二手车”的小程序,如今『BAT』小程序聚齐了,想必又会促成一番小程序的发展。
那么 F2 和小程序又如何能聊到一起?
  1. 首先,显而易见的,两者都为移动而生
  2. 其次,大数据时代(老生常谈了),需要有效的可视化工具帮助用户更好理解数据,而小程序的形态注定会产生大量数据, 有数据的地方就需要可视化,就有可视化图表的需求
  3. 最后,各个平台对于小程序的包体积都有相应的大小限制,而 F2 体积小巧完整版本 155 k,小程序版本 162 k)并且针对移动设备做了大量的性能优化,另外提供了丰富的图表类型(可绘制 45 + 图表类型)
另外也有来自很多小程序开发者的声音,他们需要 G2、ECharts 这样的可视化工具,于是致力于进行多端支持的 F2 尝试了小程序端的适配工作。

如何将 F2 运行于小程序环境

下面所指的小程序,不区分微信还是支付宝小程序,因为于 F2 而言,两种平台的封装适配方法完全相同。
首先我们需要了解下 F2 的运行环境与小程序环境的不同之处:
  1. F2 默认的运行环境是 HTML5,需要使用 <canvas> 标签、canvas 上下文以及 DOM 事件机制。
  2. 小程序虽然提供了 JavaScript 运行环境,但是它是一个没有窗口对象的环境,故不能在脚本中使用 window document 对象。
  3. 另外​,小程序提供的 canvas 上下文同 HTML5 Canvas 上下文功能虽然基本一致,但是接口不尽相同。
所以总结下来,为了能够在小程序环境中使用 F2,只需要做两方面处理:
  1. canvas 上下文部分接口的适配
2017 年 12 月,我曾经基于 F2 3.0 为支付宝小程序封装了一个组件 my-f2 用于支撑内部业务需求,当时是我第一次接触小程序的画布接口,它与 HTML5 Canvas 提供的上下文接口功能上基本一致,但是 api 接口却不尽相同,并且善有部分缺失,现将较大的差异点略举如下:
不同点
HTML5
小程序
上下文的属性设置
ctx.strokeStyle = '#1890FF';
ctx.setStrokeStyle('#1890FF');
绘制
即时绘制
需要调用 ctx.draw(reversed) 将绘图上下文中的描述绘制在 canvas 上。
缺失的 API:
  • ctx.measureText(text)
  • ctx.transform()
  • ctx.setLineDash()
全部包含
  • 微信小程序最新版本的基础库已全部提供
  • 支付宝小程序善缺失,但是可以通过一些方法进行 mock
PS: 微信小程序基础库自 1.9.90 版本起已开始支持直接属性赋值的方式 👍
于是针对以上的差异点,我专为小程序封装了一个伪 Canvas:Renderer 类,同时使用了 wolfy87-eventemitter 第三方库(该库脚本压缩后大小 3.1K)为这个 Renderer 类添加了事件机制以支持 F2 提供的交互行为,具体如何封装的,其实很简单:
  1. 属性设置上的兼容,完全可以使用 Object.defineProperty(obj, prop, descriptor) 为相关的属性提供 setter 的方法,详见 renderer.js#L38
  2. 为 Renderer 类提供 getContext(type) 方法,同 HTML5 Canvas 接口保持一致,只是返回的是经过上述包装的小程序上下文对象
  3. 对于缺失的 api,进行 mock(目前只针对支付宝小程序,微信小程序均已提供)
  1. 为上述的 canvas 对象提供一套简单的事件监听触发机制
F2 默认监听了对应 <canvas> 元素 touch 相关的事件,而小程序上不支持 document 的事件监听。不过没有关系,现在成熟的事件相关的开源库很多,我们选取了之前在 G2 中使用的 wolfy87-eventemitter(该库脚本压缩后大小 3.1K),为 Renderer 类提供事件机制的支持:
/​/ https://github.com/antvis/wx-f2/blob/master/f2-canvas/lib/renderer.js#L18
class Renderer extends EventEmitter {}​
然后覆写 F2.Util 中同事件相关的三个接口即可:
// F2.Util 中的方法:https://github.com/antvis/f2/blob/master/src/util/dom.js#L110
// 如何覆写:https://github.com/antvis/wx-f2/blob/master/f2-canvas/f2-canvas.js#L11
// override
// source 即为我们封装的 Renderer 伪 Canvas 对象
F2.Util.addEventListener = function (source, type, listener) {
  source.addListener(type, listener);
};

F2.Util.removeEventListener = function (source, type, listener) {
  source.removeListener(type, listener);
};

F2.Util.createEvent = function (event, chart) {
  // event 为小程序返回的事件对象,对于支付宝小程序有时候还需要对返回的事件坐标处理下屏幕像素比的问题
  const type = event.type;
  let x = 0;
  let y = 0;
  const touches = event.touches;
  if (touches && touches.length > 0) {
    x = touches[0].x;
    y = touches[0].y;
  }

  return {
    type,
    chart,
    x,
    y
  };
};
这样,就可以在小程序环境中愉快地使用 F2 进行可视化图表的绘制了,除了 Guide.Html(因为小程序不支持 document 对象) 无法使用外,F2 其他的功能请尽管用!同样,以上两点的处理方法也将适用于其他环境如 node、react native、weex 等,F2 多端支持的目标不会太远,也欢迎读者朋友们参与共建。

两大小程序的使用感受对比

经过此次封装,我从以下角度总结了对两个小程序框架的使用感受对比(只从我使用到的地方):
对比点
微信小程序
支付宝小程序
canvas 上下文接口
接口完善,并且更加符合 HTML5 Canvas 的国际标准
接口善有缺失
针对不同设备下的 canvas 分辨率处理
开发者无需关心,框架默认处理了
对于不同设备上的画布分辨率的处理,需要手动设置,目前我还不知道更高效通用的处理方法
文档
无论是教程还是 API 文档,都非常完善
相比微信小程序,文档还需要进一步的完善,在 api 的查找上略费力
第三方模块包的加载
目前不支持,这样就导致组件库的版本维护上略显原始,需要手动更新
支持第三方模块包的加载,对于维护以及版本管理非常方便
自定义组件的功能
提供
善未提供,但是相信很快就会上线
另外我还有一个想法:已然 HTML5 Canvas 已是一种国际标准,故认为小程序对于画布提供的 api 应该同 w3c 标准同步,这样也降低了开发者切换的成本,方法开来说,对于『BAT』这三家的小程序框架,是否也可以保持大部分的一致,以降低开发者的开发成本?

最后

最后就要隆重介绍 F2 的两个小程序版本了,欢迎大家反馈使用~~~
也请多多支持 F2,后续我们会为大家带来更多的移动端可视化体验~~~

wx-f2

F2 的微信小程序版本,该项目参考了 echarts-for-weixin 的封装思路,即封装一个了自定义组件 <ff-canvas> ,以方便用户使用。

my-f2

F2 的支付宝小程序版本(待支付宝支持自定义组件后,会基于此库提供一个支付宝小程序的组件)
微信小程序
支付宝小程序