小程序canvas生成二维码图片踩的坑

1:生成临时图片,保证画布被加载以及渲染(即本身不可以 hidden 或是 上级元素不可以 hidden 或是 wx:if 隐藏等)

== 》 建议:因为 canvas 的组件层级(z-index)是最高的,无法通过层级改变,如自定义的弹框类似的组件总会被挡住

== 》 若不想给挡住,便要控制 canvas 隐藏(hidden 、 wx:if)
但是利用 API ctx.setGlobalAlpha = 0(只是变成不透明,视觉上给隐藏,但是还是还在,若是那位置有 tap 等事件就尴尬了)

== 》 因为我只是利用 canvas生成二维码图片, swiper 轮播等使用,必须要二维码图片。

为什么要用canvas生成?

1:我自定义使用 alert 、confirm、message组件,因为canvas 组件由客户端native生成,改变不了层级,

所以总是总之 隐藏好麻烦,也解决不了我使用轮播使用二维码

2:官网(CSS动画对canvas无效)

tip: canvas 组件是由客户端创建的原生组件,它的层级是最高的,不能通过 z-index 控制层级。
tip: 请勿在 scroll-view、swiper、picker-view、movable-view 中使用 canvas 组件。
tip: css 动画对 canvas 组件无效。
bug: 避免设置过大的宽高,在安卓下会有crash的问题

解决的方法:

a:把 需要的 canvas 单独显示在屏幕外的十万八千里之外(position:fixed;top:-1000px;left:-1000px)

=》单独 单独 单独 啊 不要有父级元素(反正是用生成图片用)

注意了:保证 canvas 的 宽高与 生成二维码的宽高参数保持一致

<canvas canvas-id="QRCode-canvas-0" 
style="
	width:{{SIZE}}px;
	height:{{SIZE}}px;
	position: fixed;
	left: -500px;
	bottom: -500px;
	">
</canvas>

b:利用插件(网上很多说明 jquery-qrcode.js插件)自己参考修改成 wx 的接口的;如 使用 wepy框架 ES6语法

import {
    QRCode,
    QRErrorCorrectLevel
} from './qrcode';
import wepy from 'wepy';
export default class QRCodeMixin extends wepy.mixin {
 
    data = {
        //设置画布大小
        SIZE: 0,
 
    };
    async setSize(customSize = 150) {
        const res = await wepy.getSystemInfoSync();
        console.log('获取系统信息:*************** ', res)
            //不同屏幕下canvas的适配比例;设计稿是750宽
            // iphone6 => 180 px  deviceWidth 375px
        const scale = 375 / customSize;
        const width = res.windowWidth / scale;
        return parseInt(width);
    };
    async drawQRCode(ops = {}) {
        console.time('+++++++++++ 画布绘制总耗时:');
        const DEFAULT = {
            render: 'canvas', //设置渲染方式 (有两种方式 table和canvas,默认是canvas)
            typeNumber: 6, //计算模式   
            background: '#ffffff', //背景颜色  
            foreground: '#1A1A1A', //前景颜色
            correctLevel: QRErrorCorrectLevel.H, //纠错等级  QRErrorCorrectLevel.H, =》 L 、M 、Q 、R、 H
            canvasId: 'QRCode-canvas', //canvas对象 id
            text: 'QR-Code' //生成二维码的内容
        };
        let options = Object.assign({}, DEFAULT, {
            width: ops.size,//保持输入的宽高与canvas组件的宽高一致
            height: ops.size
        }, ops);
 
        if (!options.canvasId || options.canvasId == '') {
            throw new Error('请输入有效的画布 id !')
            return false;
        }
        const createCanvas = async(options) => {
            // create the qrcode itself
            const qrcode = new QRCode(options.typeNumber, options.correctLevel);
            qrcode.addData(options.text);
            qrcode.make();
            // get canvas context
            const ctx = wx.createCanvasContext(options.canvasId);
            console.log('++++++++++++++ 当前画布对象:', ctx);
            // compute tileW/tileH based on options.width/options.height
            const tileW = options.width / qrcode.getModuleCount();
            const tileH = options.height / qrcode.getModuleCount();
            //保存当前的绘图上下文
            ctx.save();
            // draw in the canvas
            for (let row = 0; row < qrcode.getModuleCount(); row++) {
                for (let col = 0; col < qrcode.getModuleCount(); col++) {
                    let style = qrcode.isDark(row, col) ? options.foreground : options.background;
                    ctx.setFillStyle(style);
                    let w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW));
                    let h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW));
                    ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h);
                }
            };
            //恢复之前保存的绘图上下文。
            ctx.restore();
            ctx.draw(true, () => {          
                //一定要延时一下,总是不延时,我本人的手机生成的二维码还是图片有bug
              了
                setTimeout(() => {
                    wepy.canvasToTempFilePath({
                        canvasId: options.canvasId,
                        quality: 0.9,
                        x: 0,
                        y: 0,
                        width: options.width,
                        height: options.height,
                    }).then(res => {
                        options.callback && options.callback(res.tempFilePath);
                        console.log('++++++++++++++++  wx.canvasToTempFilePath:', res);
                    });
                }, 700);
            );
            });
        };
        createCanvas(options);
    };
};

生成临时图片关键的一步:

ctx.draw(true, () => {
                setTimeout(() => {
                    wepy.canvasToTempFilePath({
                        canvasId: options.canvasId,
                        quality: 0.9,
                        x: 0,
                        y: 0,
                        width: options.width,
                        height: options.height,
                    }).then(res => {
                        options.callback && options.callback(res.tempFilePath);
                        console.log('++++++++++++++++  wx.canvasToTempFilePath:', res);

                    });
                }, 700);

            });

把混合的模块加载对应的Page 上,使用

//把二维码生成图片    const self = this;
      this.drawQRCode({
        text: ticketNo,
        size, 
        callback(tempFilePath) {
          //把二维码生成图片
          self.QRCodeFilePath = tempFilePath;
          self.$apply();
        }
      });// tempFilePath 就是上面 QRCodeMixin 封装好的生成的临时图片,再用 data 接收

坑1:刚开始经常遇到 andriad 机器生成图片白色的什么内容也没有(ios就正常) (因为没有在 wx.draw 后的回调调用)

坑2:控制台打印:canvas 为空 =》 就是上级或是本身给隐藏了(hidden 或是 wx:if)

坑3:生成的临时图片有时候正常有时候不正常(开发工具都正常的),真机就遇到 ,后来在 延时一下再执行 wepy.canvasToTempFilePath

坑4:轮播图本来用一个 canvas 画图并导出图片,可是有时候有bug的,有些二维码不正常的(所以我是用了三个 canvas 组件,递归执行完,很完美的图片出来,虽然用了三个看起来臃肿,本来使用 swier 触发再对应渲染的内容后再生成图片的)

 <canvas canvas-id="QRCode-canvas-0" style="width:{{SIZE}}px;height:{{SIZE}}px;position: fixed;left: -500px; bottom: -500px;"></canvas>
 <canvas canvas-id="QRCode-canvas-1" style="width:{{SIZE}}px;height:{{SIZE}}px;position: fixed;left: -50px; bottom: -1000px;"></canvas>
 <canvas canvas-id="QRCode-canvas-2" style="width:{{SIZE}}px;height:{{SIZE}}px;position: fixed;left: -50px; bottom: -1500px;"></canvas>

生成图片

async draw(indexValidTicketList) {
   const self = this;
   //把二维码生成图片
   self.drawQRCode({
     canvasId: 'QRCode-canvas-' + self.DRAW_QRCODE_INDEX,
     text: indexValidTicketList[self.DRAW_QRCODE_INDEX].ticketNo,
     size: self.SIZE,
     callback(tempFilePath) {
       //把二维码生成图片
       indexValidTicketList[self.DRAW_QRCODE_INDEX]['QRCodeFilePath'] = tempFilePath;
       self.$apply();
       //
       self.DRAW_QRCODE_INDEX++;
       //最多显示三张
       if (self.DRAW_QRCODE_INDEX < indexValidTicketList.length) {
         self.draw(indexValidTicketList);
       } else {
         self.DRAW_QRCODE_INDEX = 0;
         self.$apply();
       }
     }
   });
 };
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 微信小程序提供了canvas 2d的API接口用于动态生成二维码。首先,我们需要引入QRCode.js,一个专门用于生成二维码的JavaScript库。将此库导入小程序中,调用它提供的API,在canvas的画板上生成二维码。 首先,我们需要在wxml文件中添加canvas的画板: ```html <canvas canvas-id="qrcode" style="width: 300rpx; height: 300rpx;"></canvas> ``` 接着,在js文件中获取canvas元素: ```javascript const qrcode = wx.createCanvasContext('qrcode', this); ``` 生成我们需要的二维码: ```javascript qrcode.clearRect(0, 0, 300, 300); qrcode.drawImage("../../utils/qrcode.js", { width: 300, height: 300, text: "https://www.example.com" }) ``` 其中,第一个参数代表清除的矩形区域的左上角的 x 坐标,第二个参数代表清除的矩形区域的左上角的 y 坐标,第三个和第四个参数分别是矩形区域的宽度和高度。 以上代码通过引入QRCode.js库生成了一个链接为"https://www.example.com"的二维码,通过在canvas元素上绘制图案,最终生成了二维码。 需要注意的是,由于canvas是属于html5标签,所以相对于小程序的系统来说,属于一种比较“沉重”的浏览器标签。因此在微信小程序中,canvas的渲染性能可能会存在一些问题。因此在渲染过程中注意控制生成图片的大小和数量,尽量避免出现性能问题。 ### 回答2: 微信小程序是一款越来越受欢迎的移动应用程序,它具有非常丰富的功能。在微信小程序中,通过canvas 2d生成二维码,可以为小程序增加一些非常实用的功能。 二维码是一种十分方便的识别标志,通过扫描二维码可以快速打开某个页面或实现某种功能。在微信小程序中,通过canvas 2d可以轻松生成二维码。首先,需要引入一个QRCode.js插件,该插件可以在小程序中使用canvas 2d进行二维码的生成操作。 在引入QRCode.js之后,就可以开始进行二维码的生成了。通过使用QRCode.js提供的QRCode方法,可以生成一个二维码对象。接下来,通过canvas 2d的操作,可以将二维码对象绘制在小程序的指定位置上。 在绘制二维码时,需要注意以下几点。首先,需要设置二维码的大小和样式,包括背景颜色、前景颜色等。其次,需要将二维码进行缩放和平移操作,以便使其适应小程序的窗口大小和布局。最后,需要将绘制好的二维码输出到小程序canvas画布上,使其在小程序中显示出来。 通过canvas 2d生成二维码,可以为微信小程序增加很多强大的功能,如扫码登录、扫码支付等。这是一种非常方便有效的实现方式,也是目前越来越多小程序开发者选择的技术路线。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值