微信小程序:获取小程序二维码图片并且用Canvas绘制

微信小程序:获取小程序二维码图片并且用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',

									});
								}
							})
						}
					},
				})
			},
相关推荐
布瑞泽的童话11 分钟前
无需切换平台?TuneFree如何搜罗所有你爱的音乐
前端·vue.js·后端·开源
白鹭凡23 分钟前
react 甘特图之旅
前端·react.js·甘特图
2401_8628867827 分钟前
蓝禾,汤臣倍健,三七互娱,得物,顺丰,快手,游卡,oppo,康冠科技,途游游戏,埃科光电25秋招内推
前端·c++·python·算法·游戏
书中自有妍如玉35 分钟前
layui时间选择器选择周 日月季度年
前端·javascript·layui
Riesenzahn36 分钟前
canvas生成图片有没有跨域问题?如果有如何解决?
前端·javascript
f89790707038 分钟前
layui 可以使点击图片放大
前端·javascript·layui
忘不了情1 小时前
左键选择v-html绑定的文本内容,松开鼠标后出现复制弹窗
前端·javascript·html
世界尽头与你1 小时前
HTML常见语法设计
前端·html
写bug如流水1 小时前
【Git】Git Commit Angular规范详解
前端·git·angular.js