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

									});
								}
							})
						}
					},
				})
			},
相关推荐
IT_陈寒13 分钟前
JavaScript开发者必知的5个性能杀手,你踩了几个坑?
前端·人工智能·后端
跟着珅聪学java17 分钟前
Electron 精美菜单设计
运维·前端·数据库
日光倾17 分钟前
【Vue.js 入门笔记】闭包和对象引用
前端·vue.js·笔记
一只程序熊23 分钟前
UniappX 未找到 “video“ 组件,已自动当做 “view“ 组件处理。请确保代码正确,或重新生成自定义基座后再试。
前端
林小帅25 分钟前
【笔记】xxx 技术分享文档模板
前端
雾岛心情30 分钟前
【HTML&CSS】HTML为文字添加格式和内容
前端·css·html
心.c39 分钟前
如何在项目中减少 XSS 攻击
前端·xss
Rsun045511 小时前
Vue相关面试题
前端·javascript·vue.js
TON_G-T1 小时前
前端包管理器(npm、yarn、pnpm)
前端
卤炖阑尾炎1 小时前
Web 技术基础与 Nginx 网站环境部署全解析
前端·nginx·microsoft