背景 近期在开发小程序中,接触最多的就是 canvas 了,期间又因为兼容性的问题,又经历了底层 API 的新旧版的替换,踩的坑可谓令人印象深刻。小程序(微信)的 canvas 与 HTML 标准的
背景
近期在开发小程序中,接触最多的就是 canvas 了,期间又因为兼容性的问题,又经历了底层 API 的新旧版的替换,踩的坑可谓令人印象深刻。小程序(微信)的 canvas 与 HTML 标准的 canvas 有较大区别,就连小程序本身的 canvas 底层 API 都有两个大版本的区别(其实远古时期还有一个版本,但年代过于久远就不做考究了)。目前现存的两个版本的区别在于是否支持「同层渲染」。
首先,根据小程序官方的文章来看,几乎是重构了整个「原生组件」,使用方式和支持的特性与之前的区别都非常大,非常类似标准的 canvas API,甚至官方声称「支持标准 canvas 的大部分属性方法」。但是根据我的实际项目经验来看,新版 canvas API 仅仅只是在 iOS 上表现良好,在部分安卓机器上会出现许多怪异行为。一个简单的例子是绘制多个相同的形状时,画笔似乎会出现在「飘忽不定」的位置上,导致绘制最终结果无法预测。另外很让人头疼的一个地方在于 drawImage 方法上。旧版 API drawImage 第一个参数是图片路径,本地路径或网络路径皆可,但新版 API drawImage 第一个参数必须是图片实例,由于小程序无法获取 DOM 元素,只能用官方提供的 createImage 方法创建图片实例,在其 onLoad 回调中再次调用 drawImage,才能实现原先简单的方法。诸如此类。但这些都是可以克服的,最终导致我们放弃的原因是其在部分安卓机器上的「不确定性」,如果在「新特性」和「兼容性」上做选择,我想我还是坚持选择「兼容性」吧。就好像「优雅降级」和「渐进增强」,我更倾向于后者。
「兼容性」下的「同层渲染」
我相信大多数做过小程序 canvas 相关都有层级的烦恼。既然无法使用新版 API 来实现,那问题总要解决,最终我们想出了一套在旧版 API 也可以实现类似「同层渲染」的效果。目前需要「同层渲染」的场景基本上都是需要在 canvas 上弹层,所以在覆盖 canvas 的时候不会同时操作 canvas,因为可以利用canvasToTempFilePath 可以临时将 canvas 转成图片,然后隐藏 canvas,显示 tempImage 即可。
黎明的曙光
新版 canvas API 并不是一无是处,有一个很大的变化在于它不再使用物理尺寸来绘制,使用的是实际尺寸。这就会使得使用新版 API 绘制的结果比原来高清许多,这算是为数不多的优点吧。另外新版 canvas API 在 iOS 上表现还是很不错的。希望未来官方可以让新版 canvas API 兼容性更优秀,让开发者早日摆脱这些临时方案。