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

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

友情提示:本文章没有讲解Canvas基础知识点,自行了解

实用场景:

​ 我们两个大学生在开发点餐小程序,一个后端一个前端。点餐小程序,客户当然需要扫微信小程序的二维码进入小程序,并且进入时需要带参数(参数:桌号和商家id)仅仅有个二维码是不可以的,我们还得把桌号和我们的LOGO得贴上去因此想到用Canvas绘制来实现。

效果展示

实现逻辑:

首先 获取桌号与商家id –> 请求微信接口获取微信小程序的二维码–>根据需求绘制图片–>保存图片

废话少说,上手!

获取桌号与商家id

获取桌号 和 商家id 这里不展开写了,因为你项目和我这边项目中获取的方法不同,因此我们把桌号和商家id 手动给个值即可。


请求微信接口获取微信小程序的二维码

微信小程序文档地址:developers.weixin.qq.com/miniprogr...

我们获取小程序的二维码前必须首先获取 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

    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}

    //配置参数
    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

    const arrayBuffer = new Uint8Array(mationRes.data)
    const base64 = "data:image/png;base64," + uni.arrayBufferToBase64(arrayBuffer)
    return base64

整体代码片段

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片段

<view class="viewImageCard" v-show="isCanvas">
    <canvas type="2d" id="imageCod"></canvas>
    <button v-show="isCanvas" @click="setImageCode">保存图片</button>
</view>

获取二维码图片

    //获取二维码图片
    const image = await getUnlimitedQRCode(this.isSelectedTableItem.name)

获取canvas组件节点信息

因为uniapp 和 小程序不能直接获取节点信息,因此我们使用官方提供的API来获取节点信息

uniapp 节点获取信息:uni.createSelectorQuery().in(this);

为何使用 Promise :简单点说就是 因为获取节点信息,需要一定的时间 所以搞个异步来解决

//获取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参数

    //获取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)
    }

整体代码片段

            //绘画二维条码
            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转换成图片,然后调用保存接口保存图片

            //保存图片
            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',

                                    });
                                }
                            })
                        }
                    },
                })
            },
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!