微信小程序:获取小程序二维码图片并且用Canvas绘制
友情提示:本文章没有讲解Canvas基础知识点,自行了解
实用场景:
我们两个大学生在开发点餐小程序,一个后端一个前端。点餐小程序,客户当然需要扫微信小程序的二维码进入小程序,并且进入时需要带参数(参数:桌号和商家id)仅仅有个二维码是不可以的,我们还得把桌号和我们的LOGO得贴上去因此想到用Canvas绘制来实现。
效果展示
实现逻辑:
获取桌号与商家id --> 请求微信接口获取微信小程序的二维码-->根据需求绘制图片-->保存图片
废话少说,上手!
获取桌号与商家id
获取桌号 和 商家id 这里不展开写了,因为你项目和我这边项目中获取的方法不同,因此我们把桌号和商家id 手动给个值即可。
请求微信接口获取微信小程序的二维码
微信小程序文档地址:developers.weixin.qq.com/miniprogram...
我们获取小程序的二维码前必须首先获取 ACCESS_TOKEN 然后 去请求获取小程序二维码的接口并且把返回的图片二进制转换成Base64
获取ACCESS_TOKEN
ACCESS_TOKEN请求接口:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}
请求时您需要配置自己的微信小程序APPID和APPSECRET
javascript
const APPID = 'wx77328d********';
const APPSECRET = '5331e159637c0a***********';
//获取ACCESS_TOKEN
const tokenRes = await uni.request({
url: `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}`,
method: 'GET',
})
const ACCESS_TOKEN = tokenRes.data.access_token
获取小程序二维码
小程序二维码获取接口:https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${ACCESS_TOKEN}
javascript
//配置参数
const data = {
"page": "pages/index/index", //进入程序页面路径
"scene": `tableId=${parameter}`, // 二维码带的参数
"check_path": true, //默认是true
"env_version": "release" //要打开的小程序版本
}
//请求接口
const mationRes = await uni.request({
header: {
"Content-Type": "application/x-www-form-urlencoded"
},
method: 'POST',
url: `https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${ACCESS_TOKEN}`,
data: JSON.stringify(data), //把data需要转换成json格式 否则请求失败
responseType: 'arraybuffer'
})
获取完成后,返回的图片二进制转换成Base64
javascript
const arrayBuffer = new Uint8Array(mationRes.data)
const base64 = "data:image/png;base64," + uni.arrayBufferToBase64(arrayBuffer)
return base64
整体代码片段
javascript
export async function getUnlimitedQRCode(parameter) {
const APPID = 'wx77328d********';
const APPSECRET = '5331e159637c0ac**************';
//获取ACCESS_TOKEN
const tokenRes = await uni.request({
url: `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}`,
method: 'GET',
})
const ACCESS_TOKEN = tokenRes.data.access_token
const data = {
"page": "pages/index/index",
"scene": `id=${parameter},shopId='456456489'`,
"check_path": true,
"env_version": "release"
}
//请求获取二维码
const mationRes = await uni.request({
header: {
"Content-Type": "application/x-www-form-urlencoded"
},
method: 'POST',
url: `https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${ACCESS_TOKEN}`,
data: JSON.stringify(data),
responseType: 'arraybuffer'
})
//转换Base64
const arrayBuffer = new Uint8Array(mationRes.data)
const base64 = "data:image/png;base64," + uni.arrayBufferToBase64(arrayBuffer)
return base64
}
根据需求绘制图片
我们首先获取二维码图片,然后获取canvas组件的节点信息,然后初始化并且设置canvas参数(防止放大2倍),绘制背景图片,绘制二维码
HTML片段
html
<view class="viewImageCard" v-show="isCanvas">
<canvas type="2d" id="imageCod"></canvas>
<button v-show="isCanvas" @click="setImageCode">保存图片</button>
</view>
获取二维码图片
javascript
//获取二维码图片
const image = await getUnlimitedQRCode(this.isSelectedTableItem.name)
获取canvas组件节点信息
因为uniapp 和 小程序不能直接获取节点信息,因此我们使用官方提供的API来获取节点信息
uniapp 节点获取信息:uni.createSelectorQuery().in(this);
为何使用 Promise :简单点说就是 因为获取节点信息,需要一定的时间 所以搞个异步来解决
javascript
//获取canvasDom节点
getCanvasDom() {
return new Promise((resolve, reject) => {
const query = uni.createSelectorQuery().in(this);
query.select('#imageCod').node((res) => {
if (res.node) {
resolve(res.node)
} else {
reject('出错误了')
}
}).exec()
})
}
初始化并且设置canvas参数
javascript
//获取canvas组件的节点信息
const canvasNodeDom = await this.getCanvasDom()
const ctx = canvasNodeDom.getContext('2d')
//设置canvas 参数 防止图片放大2倍
const dpr = wx.getSystemInfoSync().pixelRatio
//宽高乘像素比
canvasNodeDom.width = 400 * dpr
canvasNodeDom.height = 520 * dpr
//再缩放
ctx.scale(dpr, dpr)
ctx.fillRect(0, 0, 100, 100)
绘制背景图:这里自己准备背景图
javascript
//绘制背景图片
const backgroundImage = canvasNodeDom.createImage()
backgroundImage.src = tableCodeImageBackgrond
backgroundImage.onload = () => {
ctx.drawImage(backgroundImage, 0, 0, 400, 520)
}
绘制二维码和桌号
javascript
const imageCode = canvasNodeDom.createImage()
imageCode.src = image.base64
imageCode.onload = () => {
//绘制二维码
ctx.drawImage(imageCode, 80, 160, 240, 240)
ctx.fillStyle = '#2b85e4';
//绘制桌号
ctx.font = 'bolder 50px 楷体';
ctx.fillText(`${image.parameter}`, 170, 480)
}
整体代码片段
javascript
//绘画二维条码
async paintingTableViewCode() {
try {
//获取二维码图片
const image = await getUnlimitedQRCode(this.isSelectedTableItem.name)
//获取canvas组件的节点信息
const canvasNodeDom = await this.getCanvasDom()
const ctx = canvasNodeDom.getContext('2d')
//设置canvas 参数 防止图片放大2倍
const dpr = wx.getSystemInfoSync().pixelRatio
//宽高乘像素比
canvasNodeDom.width = 400 * dpr
canvasNodeDom.height = 520 * dpr
//再缩放
ctx.scale(dpr, dpr)
ctx.fillRect(0, 0, 100, 100)
//绘制背景图片
const backgroundImage = canvasNodeDom.createImage()
backgroundImage.src = tableCodeImageBackgrond
backgroundImage.onload = () => {
ctx.drawImage(backgroundImage, 0, 0, 400, 520)
}
//绘制二维码
const imageCode = canvasNodeDom.createImage()
imageCode.src = image.base64
imageCode.onload = () => {
ctx.drawImage(imageCode, 80, 160, 240, 240)
ctx.fillStyle = '#2b85e4';
ctx.font = 'bolder 50px 楷体';
ctx.fillText(`${image.parameter}`, 170, 480)
}
this.isCanvas = true //是否绘制完成
} catch {
uni.showToast({
title: '图片加载失败',
duration: 2000,
icon: 'error',
});
this.viewImageCardShow = false //关闭查看二维码窗口
}
}
保存图片
我们首先获取刚才生成的canvas节点,然后调用微信小程序接口把canvas转换成图片,然后调用保存接口保存图片
javascript
//保存图片
async setImageCode() {
//获取canvas组件的节点信息
const canvas = await this.getCanvasDom()
//生成图片
wx.canvasToTempFilePath({
canvas: canvas,
fileType: 'png',
success: (res) => {
if (res) {
//生成图片的地址
const url = res.tempFilePath
//保存图片
wx.saveImageToPhotosAlbum({
filePath: url,
success: (res) => {
this.viewImageCardShow = false
},
fail: () => {
uni.showToast({
title: '图片保存失败',
duration: 2000,
icon: 'error',
});
}
})
}
},
})
},