刚做完一个微信小程序的项目,现在对项目里的一些功能进行整理,这篇文章记录下如何在小程序里实现生成带有二维码的海报,并保存到用户相册。以此文章记录,便于后续项目使用。项目是基于mpvue做的。
项目要求每个用开通金镶玉小程序电话:4006-838-530户可以生成一个属于自己的推广二维码,拉新后记录推广人。生成的海报最终效果也不复杂,如图:
下面保存图片是个白底的按钮,跟背景色混一块就看不到了。。。
需求分析通过查阅微信小程序的文档得知,可以借助于小程序提供的canvas绘图功能根据设计图来绘制个canvas图,然后通过保存图片到相册这个API把图片保存到用户的手机相册。海报中有些内容是固定不变的,比如背景图、邀请话术以及下面长按图片的提示语,而还有些内容是动态的,比如用户名和小程序码,不同项目需求不一样,但都会有变动和不变两类内容,然后我们根据设计图一点一点把内容绘制到图上就行啦。知道要做什么了,那么我们来罗列下要做的事情(吉德林法则有云:把要解决的问题清清楚楚的列下来,问题就解决了一半)获取用户名获取用户专属小程序码图片绘制处理用户取消保存到相册的授权
动手实现
首先在页面里插入个canvas标签,并把它的位置调整到界面外。至于为啥是通过控制位置而不是控制显示隐藏,动手试过的兄弟都应该知道,优先级问题。
- 首先在页面里插入个canvas标签,并把它的位置调整到界面外。至于为啥是通过控制位置而不是控制显示隐藏,动手试过的兄弟都应该知道,优先级问题。
canvas class="cv-ct-canvas" canvas-id="cv-pic"/canvas.cv-ct-canvas { position: absolute; left: 800rpx; width: 300px; height: 500px;}复制代码
- 准备用户名、小程序码。因为我这里的背景图也是个远程图片,所以也一并要先下载。
const { tempFilePath: bg } = await this.downloadFile('$(STATICFILE_URL)/prom-share-bg.png')let name = this.userInfo.NickName;// 下载图片到本地const { tempFilePath } = await this.downloadFile(this.qrcodeUrl);复制代码
这里要说明下,这个downloadFile方法是把微信的downloadFile方法进行了同步处理,其实很简单,就是用个Promise包裹一下。
- 往画布上逐个绘制。
const ctx = wx.createCanvasContext("cv-pic");// 填充背景色ctx.setFillStyle("#f8f8f8");ctx.fillRect(0, 0, 300, 400);ctx.fill();ctx.setFillStyle("#ffffff");ctx.fillRect(0, 400, 300, 100);ctx.fill();// 填充背景图ctx.drawImage(bg, 30, 20, 240, 365);// 写入名字ctx.setFontSize(15);ctx.setFillStyle("#FFF9F0");ctx.fillText(name, 61, 300);// 写两行提示ctx.setFillStyle("#322F30");ctx.setFontSize(14);ctx.fillText("长按识别小程序码", 33, 440);ctx.fillText("超值礼包等你来抢", 33, 465);// 填充小程序码ctx.drawImage(tempFilePath, 0, 0, 280, 280, 200, 410, 80, 80);const that = this;// 把canvas图保存到临时目录ctx.draw(false, function() { wx.canvasToTempFilePath({ canvasId: "cv-pic", success(res) { let url = res.tempFilePath; that.savePic = url; } });});复制代码
在最后用canvasToTempFilePath把图片先保存到了临时目录,并把临时目录的地址赋值给了savePic,因为界面上要展示这个图,所以在界面上会有个Image标签,这个标签的地址就是savePic。
- 保存到用户相册,代码比较简单,直接上:
if (!this.savePic) return; const that = this; wx.saveImageToPhotosAlbum({ filePath: this.savePic, success: f开通三洋小程序电话:4006-838-530unction() { that.showSaveCode = false; wx.showToast({ title: "保存成功", icon: "success", duration: 2000 }); }, fail: function () { that.getWriteToAlbumSetting() } });复制代码
对于最后这个fail里面的getWriteToAlbumSetting方法,下面作解释。
- 处理用户拒绝授权。对于需要用户授权的操作,我们现在是这么处理的:
先在页面data里声明一个变量表示当前用户是否已经授权了,比如这里我声明了canWriteToAlbum用来表示是否可以保存图片到相册。然后在页面加载时,如在mounted钩子函数里执行一次getWriteToAlbumSetting这个方法,该方法主要是通过wx.getSetting获取当前用户是否已经授权,代码如下:async getWriteToAlbumSetting() { // this.getSetting 方法也是对wx.getSetting的一个同步封装处理 let status = awa开通铁观音小程序电话:4006-838-530it this.getSetting('writePhotosAlbum') // 因为用户第一次进行操作的时候,授权状态为undefined,只有在明确拒绝过的时候才会是false if (status === true || status === undefined) { this.canWriteToAlbum = true } else { this.canWriteToAlbum = false }}复制代码
在页面中,根据用户的授权情况,显示表面相同其实不同的操作按钮:div class="cv-save" @click="saveToPhotosAlbum" v-if="canWriteToAlbum"保存图片/divdiv class="cv-save" @click="openAlbumSetting" v-else保存图片/div复制代码
至于为什么要这么做,当然还是因为小程序的限制啦。如果用户拒绝过授权,再次点击保存按钮,要弹出授权界面,而微信明确要求,弹出授权界面必须是用户直接点击按钮触发,所以只能这样实现了。openAlbumSetting代码如下:async openAlbumSetting() { // 还是对微信API的同步封装 let status = await this.openSetting('writePhotosAlbum') // false表示又拒绝了 if (status === false) return // 只有明确授权了才进行保存到相册的操作 this.canWriteToAlbum = true this.saveToPhotosAlbum()}复制代码
最新评论