原因:界面上有保存图片、在微信端分享的需求,以前有类似功能,前端实现页面模板,通过后端使用PhantomJS 无界面的浏览器组件渲染后进行截图实现,但生成过程较慢,经商议本次通过前端实现保存图片功能
目的:通过把页面用canvas绘制,从而导出为图片保存在手机。
介绍:不同于h5有许多调用简单、可以截取页面的成熟插件,在微信小程序上绘制canvas 除了使用原生canvas外,官方提供了wxml-to-canvas组件。尽管并不完善,但相比直接canvas绘制,方便了序多,另外还有Painter (第三方组件)也类似。
问题:组件渲染支持view、image、text 标签。默认flex布局,引入的图片地址需要是https 开头的网络图片地址,所有文字内容要用text标签包裹、并且需要指定宽高,文字不会自动换行,超出部分会截断。所以相较于静态页面,对于动态获取数据的页面,需要计算宽高及位置
1、组件在真机上不展示,提示canvas has not been created。
解决方法:npm构建后发现 ,miniprogram_npm/wxml-to-canvas/index.js 文件内,sdk版本在2.9.2 后可用canvas 2d 接口,
真机上版本较低,于是注释并设置值为false,在真机上展示出来了
2、计算所有元素宽高位置
解决:由于页面内容大部分动态获取、宽高不定,全部计算工作量很大,用了比较笨的方法,先布局出一模一样的wxml页面,渲染后,通过
query = wx.createSelectorQuery().in(this)
query.select('.demo').boundingClientRect(res=>{}).exec()
获取每个元素的宽高位置后赋值实现,与此同时,文字的行距、字号大小无法获取,需要根据设计图和页面比例另外计算,注意:Dpr为2和3时的字号大小有区别
3、不支持字体加粗
解决方法:同上,在index.js文件内,修改代码实现。但是注意,在使用fontWeight:"bold"后的文字都变成加粗,网上有人推荐加粗写在最后,可避免影响其他的样式,试过后依然会影响。
结果:放弃使用加粗
4、图片变形:绘制出的image,无法等比显示,图片要么压缩,要么被拉伸,效果较差,
结果:未解决
5、渲染:canvas需要在页面资源加载完成后再创建渲染,否则会失败。
问题: 保存为图片的时间非常久
结果:后来经查询,设置图中两个属性后,保存图片速度提升很多。
结果:由于图片内容和尺寸关系,保存时间最终在3-5秒之间
综合结论:
虽然保存长图最终在3-5秒之间,比后台截图快了一些,但不如预期。
考虑到投入工作量、解决兼容性问题消耗的时间和最终保存图片的效果来看,对于宽高动态计算的页面,推荐前端实现模板,后台截图实现保存效果更好。
对于在微信小程序上的同类型保存功能,前端比较适合实现简单布局的页面图片保存。