Canvas是基于位图的图像,最常见的用途是通过擦除重绘渲染图像,绘制含有大量元素的图表,适合像素处理,动态渲染和大数据量绘制,使用JavaScript程序绘图。
普通的Canvas
Canvas是绘图环境的容器,默认宽300px,高150px,微信小程序开发文档里写的高225px,经验证后果然是微信文档写错了。
它有一个getContext方法,传入2d是我们最常用的平面绘制,传入webgl用来开启GPU加速渲染。这个方法返回一个context, context是状态机,可以改变状态,几乎所有的渲染操作的最终效果与context本身的状态有关系。
神奇的原生组件
在开发小程序的过程中经常遇到这样的问题:原生组件的层级是最高的,所以页面中的其他组件无论设置z-index为多少,都无法盖在原生组件上。例如camera、input、live-player、live-pusher、map、textarea、video,当然还有canvas。
缘起·原生组件(1)
在搞清楚原生组件这个奇怪的特性之前,先要明白微信小程序是怎么来的:
做过微信网页开发的同学应该很熟悉基于JS-SDK的微信内嵌网页,这种网页缺点很多,性能差,加载慢,白屏,页面切换生硬等等,开发者没有足够的时间优化页面体验。微信面对这个痛点,想不如干脆我们做好基础框架开放给开发者好了,就是17年推出的小程序。
考虑小程序架构设计的技术选型,要求只有一个,就是要快,渲染快、加载快。此时有三种方案可供选择:
一是纯客户端原生技术渲染,但是小程序的宿主环境是微信,不可能跟着微信代码一起编包发版,于是否掉了。
二是纯Web渲染,但是我们知道JS是单线程执行,逻辑任务会抢占UI渲染的资源,于是也否掉了。
三是两种混合模式的Hybrid技术,使用Web技术渲染,辅之以客户端原生的接口。
微信选择了第三种方案。
缘起·原生组件(2)
界面渲染相关的任务在WebView线程里执行,这就是渲染层。渲染层定义了一套内置组件以统一体验,包括视图容器类、表单类、导航类、媒体类、开放类等几十种组件。内置组件有一部份较复杂组件是用客户端原生渲染的。
使用Web技术渲染是存在安全风险的。微信有很多敏感数据,小程序提供了一些可以展示敏感数据的组件,例如open-data,浏览器的JS包含DOM和BOM,如果开发者可以通过操作DOM获取敏感数据,或者利用浏览器一些开放性接口,那小程序毫无安全可言。
于是JS代码要放在沙箱环境运行,创建一个单独的线程,使用客户端系统的JS解释引擎,只执行小程序的业务逻辑代码,这就是逻辑层。(iOS是用内置的JavaScriptCore框架,在安卓则是用腾讯x5内核提供的JsCore环境)
双线程模型:
组件被插入到DOM树里,浏览器内核会立即计算布局,读取出组件相对页面的位置、宽高。客户端在相同的位置上,根据宽高插入一块原生区域,之后客户端就在这块区域渲染界面,原生界面叠在客户端在占位元素上,因此,原生组件的层级会比所有在WebView层渲染的普通组件要高。
小程序Canvas的其他坑
1,图片文字小容易失真
解决方法:把画布放大X倍
2,图片服务器地址需要先下载到本地缓存
使用wx.getImageInfo(url),同时管理后台需要设置域名
3,不支持文字排版
解决方法:利用context.measureText(string text)封装计算文字宽度的方法
4,多种样式串行
动画渲染每一帧的时间只有16ms,所以JavaScript层面消耗的时间最好控制在10ms以内,除非计算很复杂,渲染比计算的开销大很多。
解决方法:尽量少更改开销大的属性,例如lineWidth,字体样式