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

									});
								}
							})
						}
					},
				})
			},
相关推荐
崔庆才丨静觅2 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了2 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅2 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅3 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅3 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment3 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅4 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊4 小时前
jwt介绍
前端
爱敲代码的小鱼4 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax