刚作完一个微信小程序的项目,如今对项目里的一些功能进行整理,这篇文章记录下如何在小程序里实现生成带有二维码的海报,并保存到用户相册。html
以此文章记录,便于后续项目使用。vue
项目是基于mpvue作的。canvas
每一个用户能够生成一个属于本身的推广二维码,拉新后记录推广人。小程序
生成的海报最终效果也不复杂,如图:微信小程序
经过查阅微信小程序的文档得知,能够借助于小程序提供的canvas绘图功能根据设计图来绘制个canvas图,而后经过保存图片到相册这个API把图片保存到用户的手机相册。api
海报中有些内容是固定不变的,好比背景图、邀请话术以及下面长按图片的提示语,而还有些内容是动态的,好比用户名和小程序码,不一样项目需求不同,但都会有变更和不变两类内容,而后咱们根据设计图一点一点把内容绘制到图上就行啦。bash
知道要作什么了,那么咱们来罗列下要作的事情(吉德林法则有云:把要解决的问题清清楚楚的列下来,问题就解决了一半)微信
<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包裹一下。async
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: function() {
that.showSaveCode = false;
wx.showToast({
title: "保存成功",
icon: "success",
duration: 2000
});
},
fail: function () {
that.getWriteToAlbumSetting()
}
});
复制代码
对于最后这个fail里面的getWriteToAlbumSetting方法,下面做解释。
async getWriteToAlbumSetting() {
// this.getSetting 方法也是对wx.getSetting的一个同步封装处理
let status = await 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">保存图片</div>
<div 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()
}
复制代码
这篇文章除了记录对于生成分享海报的实现外,主要还说明了如何处理用户拒绝受权的状况,这里虽然只说了对于拒绝保存图片的受权,但对于其余操做的受权拒绝处理也能够这样。
第一次写文章,有点乱,之后慢慢练习吧~~~