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