生成图片这个功能需要使用 Canvas ,先将要保存的图片使用 Canvas 画出来,然后调用相关方法保存到手机上。文中使用或是未使用的有关小程序中 Canvas 的 api 可以在 小程序Canvas相关Api 这里查看。
为了使用方便,我将这个需求的实现做成了一个组件,便于项目的其他地方复用,也遇到了一些因为使用自定义组件带来的问题
<!–more–>
要实现的效果图
实现思路
相关的代码比较长,而且大部分为调用 Canvas 的 api 代码,整体贴出无必要。本文中只描述思路,具体代码看 小程序生成图片的微信代码片段 。
代码中的几个方法
drawRoundedRect
:用来绘制圆角矩形,此处不详述它的画图原理point
:为方法 1 服务的,一看就懂downFile
:对微信的下载方法进行了一层简单封装,传入 url ,返回一个 Promisesave
: 保存图片的相关逻辑doAuth
:当调用wx.saveImageToPhotosAlbum
方法保存图片时,如果没有保存图片的权限会保存失败,此时需要让用户重新授权computedPercent
:一个快捷的计算比例的方法,传入从设计图上量出来的像素数即可,oldWidth
是设计图上的 Canvas 区域宽度initData
:数据初始化,获取设备相关信息,将网络图下载到本地writeCanvas
: 主要画图逻辑,调用此方法时保证所需数据已处理完毕,开始画图
数据初始化
需求中需要显示用户头像和小程序码,小程序码后面是要挂参数的,可以简单理解为要挂个用户参数在后面,类似这样 ?uid=2233
,这就是组件中要传入的 scene 的值,然后根据这个参数,在开始画图之前,先调用接口从服务端那里获取图片的链接,再利用微信的 wx.downloadFile
方法将图片下载到本地,在 Canvas 中使用本地路径,用户头像和小程序码都下载好了之后就可以开始画图了,否则的话,提示网络错误。
为了演示方便,本文中的网络图都换成了本地图片
画图
由于是在组件中,所以获取 Canvas 上下文的时候要传入 this
,根据设计图,从里向外依次往 Canvas 上叠加就是了,从设计图上量出的像素调用方法来获取比例,画完之后调用 Canvas 的 draw
方法技术绘画,并且将 loading 状态取消
保存图片
保存图片的时候,要注意保存的图片的宽高都乘一下设备的像素比,防止出来的图片太小了,保存图片需要相关权限,若用户为授权,要弹窗让他授权之后再进行保存操作
遇到的问题
以下部分问题有时效性,请大家理性看待。
- canvas 结束绘画要调用
ctx.draw()
方法,不调用的话是什么都不会显示的 wx.createCanvasContext(string canvasId, Object this)
,在自定义组件下,当前组件实例的this
,表示在这个自定义组件下查找拥有canvas-id
的<canvas>
,如果省略则不在任何自定义组件内查找。简而言之就是在页面级调用这个方法的时候,第二个参数可以不传,会默认传入 this ;但是在自定义组件中调用这个方法的话,要传入 this- 部分手机上保存的图片分辨率太小,导致图片上的字看不清。最后使用了一个百分比的计算,所有的的坐标或者大小都是根据屏幕宽高和设计图宽高比例计算出来了,这样可以保证即使在不同手机上或者在不同的容器中,都是有恰当比例的;并且保存图片的时候,要注意保存的图片的宽高都乘一下设备的像素比
- Canvas 中不能放网络图,所以网络图需要先下载到本地之后在使用
- 如果用到了下载网络图片的话,别忘记设置微信的
downloadFile
合法域名
结语
对于大部分同学来说,自己项目的需求和我这里实现的可能是有些出入的,所以本文只是起到一个例子的作用,可以帮助你快速上手这个模块的开发
贴个源码吧