Vue2使用qrcode.js+canvas实现二维码下载,自定义顶部底部文字和logo

写项目的时候有个需求是在vue的表格中,用户点击下载按钮,自动下载二维码,且二维码上下方展示一些信息。

起初我选用了简洁易写的qrcode.js2,代码如下

<el-table v-loading="loading" :data="noticeList" @selection-change="handleSelectionChange">
            <el-table-column type="selection" width="55" align="center" />
            <el-table-column label="日期" align="center" prop="date" />
            <el-table-column label="名称" align="center" prop="name" />
            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
                <template slot-scope="scope">
                    <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改
                    </el-button>
                    <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除
                    </el-button>
                    <el-button size="mini" type="text" icon="el-icon-download" @click="createQRCode(scope.row)">导出二维码
                    </el-button>
                </template>
            </el-table-column>
             <div id="qrcode" ref="qrCodeDiv" style="width: 300px;height: 300px">
            </div> 
  </el-table>
    


 createQRCode(row) {
             const prefix = this.qrPrefix
             document.getElementById("qrcode").innerHTML = ""
             let qrcode = new QRCode(this.$refs['qrCodeDiv'], {
                 text: prefix + '' + row.id,
                 width: 200, //二维码的宽度
                 height: 200, //二维码的高度
                 colorDark: "#666666", // 二维码的深色部分
                 colorLight: "#ffffff", //二维码的浅色部分
                 correctLevel: QRCode.CorrectLevel.H,//纠错级别,L,M,Q,H,由低到高
             })
             this.downloadQRCode(row.Name)
         },
downloadQRCode(name) {
            let qrcode = document.getElementById('qrcode');
            let img = qrcode.getElementsByTagName('img')[0];
            img.onload = function () {
                this.imgUrl = img.getAttribute("src");
                let link = document.createElement("a");
                link.setAttribute("href", this.imgUrl);//指定href
                link.setAttribute("download", name+ '.png')//指定文件名
                link.click();
            }
        },

使用qrcode.js2生成二维码相对简单易操作,但是同时其提供的api较少,所以很难满足需求。

为了实现需求,我尝试了vue-qr和qrcode.js,最终选择了qrcode.js,参考了其他博主的一些文章与代码,改进后的代码如下

<el-table v-loading="loading" :data="noticeList" @selection-change="handleSelectionChange">
            <el-table-column type="selection" width="55" align="center" />
            <el-table-column label="日期" align="center" prop="date" />
            <el-table-column label="名称" align="center" prop="name" />
            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
                <template slot-scope="scope">
                    <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改
                    </el-button>
                    <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除
                    </el-button>
                    <el-button size="mini" type="text" icon="el-icon-download" @click="createQRCode(scope.row)">导出二维码
                    </el-button>
                </template>
            </el-table-column>
              <div id="qrcode" :title="qrText">
     <div class="qrcode_box">
         <img class="qrcode_canvas" id="qrcode_canvas" ref="qrcode_canvas" alt="二维码" />
          <img v-if="qrLogo" class="qrcode_logo" ref="qrcode_logo" :src="qrLogo" alt="logo" />
         <canvas :width="qrSize" :height="qrSize" class="canvas" ref="canvas"></canvas>
     </div>
 </div>
  </el-table>





import QRCode from "qrcode";
export default {
    name: "qrsign",
    props: {
        qrUrl: {
            type: String,
            default: "https://www.baidu.com"
        },
        qrSize: {
            type: Number,
            default: 300
        },
        qrText: {
            default: "百度,百度,百度"
        },
        qrLogo: {
             type: String,
            default: logo
        },
        qrLogoSize: {
            type: Number,
            default: 40
        },
        qrTextSize: {
            type: Number,
            default: 14
        }
    },

    methods: {
        createQRCode(row) {
            const prefix = this.qrPrefix
            this.qrText = row.date+"    "+row.name//底部文字
            let topText = row.name//顶部文字
            this.qrUrl = prefix+ row.id//url,二维码内容,或跳转链接
            let qrcode_canvas = this.$refs.qrcode_canvas;
            let qrcode_logo = this.$refs.qrcode_logo;
            let canvas = this.$refs.canvas;
            const that = this;
            QRCode.toDataURL(
                this.qrUrl,
                { errorCorrectionLevel: "H" },
                (err, url) => {
                    qrcode_canvas.src = url;
                    // 画二维码里的logo// 在canvas里进行拼接
                    let ctx = canvas.getContext("2d");
                    setTimeout(() => {
                        //使用setTimeout变为异步
                        //获取图片
                        ctx.drawImage(qrcode_canvas, 0, 0, that.qrSize, that.qrSize);
                        if (that.qrLogo) {
                            //设置logo大小
                            //设置获取的logo将其变为圆角以及添加白色背景
                            ctx.fillStyle = "#fff";
                            ctx.beginPath();
                            let logoPosition = (that.qrSize - that.qrLogoSize) / 2; //logo相对于canvas居中定位
                            let h = that.qrLogoSize + 10; //圆角高 10为基数(logo四周白色背景为10/2)
                            let w = that.qrLogoSize + 10; //圆角宽
                            let x = logoPosition - 5;
                            let y = logoPosition - 5;
                            let r = 5; //圆角半径
                            ctx.moveTo(x + r, y);
                            ctx.arcTo(x + w, y, x + w, y + h, r);
                            ctx.arcTo(x + w, y + h, x, y + h, r);
                            ctx.arcTo(x, y + h, x, y, r);
                            ctx.arcTo(x, y, x + w, y, r);
                            ctx.closePath();
                            ctx.fill(); qrcode_logo.onload = function () {
                                ctx.drawImage(
                                    qrcode_logo,
                                    logoPosition,
                                    logoPosition,
                                    that.qrLogoSize,
                                    that.qrLogoSize
                                );
                            }
                        }
                        if (that.qrText) {
                            //设置字体
                            let fpadd = 10; //规定内间距
                            ctx.font = "bold " + that.qrTextSize + "px Arial";
                            let tw = ctx.measureText(that.qrText).width; //文字真实宽度
                            let ftop = that.qrSize - that.qrTextSize; //根据字体大小计算文字top
                            let fleft = (that.qrSize - tw) / 2; //根据字体大小计算文字left
                            let tp = that.qrTextSize / 2; //字体边距为字体大小的一半
                            ctx.fillStyle = "#fff";
                            ctx.fillRect(
                                fleft - tp / 2,
                                ftop - tp / 2,
                                tw + tp,
                                that.qrTextSize + tp
                            );
                            ctx.textBaseline = "top"; //绘制文本时的文本基线
                            ctx.fillStyle = "#333";
                            ctx.fillText(that.qrText, fleft, ftop);//canvas填充文字   
      
                        }
                        if (topText) {
                            //设置字体
                            let fpadd = 10; //内间距
                            ctx.font = "bold " + that.qrTextSize + "px Arial";
                            let tw = ctx.measureText(topText).width; //文字真实宽度
                            let ftop = 5
                            let fleft = (that.qrSize - tw) / 2; //根据字体大小计算文字left
                            let tp = that.qrTextSize / 2; //字体边距为字体大小的一半
                            ctx.fillStyle = "#fff";
                            ctx.fillRect(
                                fleft - tp / 2,
                                ftop - tp / 2,
                                tw + tp,
                                that.qrTextSize + tp
                            );
                            ctx.textBaseline = "top"; //绘制文本时的文本基线
                            ctx.fillStyle = "#333";
                            ctx.fillText(topText, fleft, ftop);//canvas填充文字     
                        }      
                        qrcode_canvas.src = canvas.toDataURL();
                        this.downloadQRCode(qrcode_canvas,row.name)
                    }, 0);
                }
            );
        },
        downloadQRCode(image,name) {
            let img = image
            img.onload = function () {
                this.imgUrl = img.getAttribute("src");
                let link = document.createElement("a");
                link.setAttribute("href", this.imgUrl);
                link.setAttribute("download", name + '.png')
                link.click();
            }
        }
    }
};

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值