在Vue中用canvas实现二维码和图片合成海报

算法流星
• 阅读 9448

在项目中经常会遇到需要将不同的二维码放到一张通用图片上,提供用户下载
简单来说,就是利用canvas将同等比例的二维码在图片上叠加,生成海报


1. 设置相应比例

一般来说海报背景都是固定的,可以直接放在public文件夹,二维码可根据后台返回数据,也可用canvas生成,在此不多赘述

import posterBgImg from '../public/images/poster_bg.png';// 海报底图
import qrcodeImg from '../public/images/qrcode.png';// 二维码
export default{
    name: 'qrcode-in-poster',
    data(){
        return {
            posterBgImg,
            qrcodeImg,
            posterSize: 930/650,// 海报高宽比例
            qrCodeSize: {// 二维码与海报对应比例 =》 用于设置二维码在海报中的位置
                width: 270/650,
                height: 270/930,
                left: 190/650,
                top: 448/650
            },
            poster: '',// 合成图片
        }
    }
};

2. 获取屏幕宽度

限定移动端最大宽度为 480px

computed: {
    screenWidth(){
        let w = document.body.clientWidt || document.documentElement.clientWidth || 375;
        return w > 480 ? 480 : w ;
    }
};

3. 组合图片

methods: {
    combinedPoster(_url){
        let that = this,
            qrcode = this.qrcodeImg; // 二维码地址
    
        console.log("open draw: ", _url, qrcode)
        let base64 = '',
            canvas = document.createElement('canvas'),
            ctx = canvas.getContext("2d"),
            _w = this.screenWidth * 2, // 图片宽度: 由于手机屏幕时retina屏,都会多倍渲染,在此只设置2倍,如果直接设置等于手机屏幕,会导致生成的图片分辨率不够而模糊
            _h = this.posterSize * _w, // 图片高度
            _qr_w = this.qrCodeSize.width * _w, // 二维码宽 = 比例 * 宽度
            _qr_h = this.qrCodeSize.height * _h, // 二维码高 = 比例 * 高度
            _qr_t = this.qrCodeSize.top * _w, // 二维码顶部距离 = 比例 * 宽度
            _qr_l = this.qrCodeSize.left * _w; // 二维码左侧距离 = 比例 * 宽度
        // 设置canvas宽高    
        canvas.width = _w; 
        canvas.height = _h;
        ctx.rect(0, 0, _w, _h);
        ctx.fillStyle = '#fff'; // 填充颜色
        ctx.fill();
        // 迭代生成: 第一层(底图)+ 第二层(二维码)
        // file:文件,size:[顶部距离,左侧距离,宽度,高度]
        let _list = [ 
            {
                file: _url,
                size: [0, 0, _w, _h]
            }, {
                file: qrcode,
                size: [_qr_l, _qr_t, _qr_w, _qr_h]
            }
        ];
        // 开始绘画
        let drawing = (_index) => {
            // 判断当前索引 =》 是否已绘制完毕
            if (_index < _list.length) {
                // 等图片预加载后画图
                let img = new Image(),
                    timeStamp = new Date().getTime();
                // 防止跨域
                img.setAttribute('crossOrigin', 'anonymous')
                // 链接加上时间戳
                img.src = _list[_index].file + '?' + timeStamp
                img.onload = function() {
                    // 画图
                    ctx.drawImage(img, ..._list[_index].size)
                    // 递归_list
                    drawing(_index + 1)
                }
            } else {
                // 生成图片
                base64 = canvas.toDataURL("image/png")
                if (base64) {
                    // 赋值相应海报上
                    this.$set(that, 'poster', base64)
                }
            }
        }
        drawing(0)
    }
};
mounted(){
    // 需要合成海报的图片
    this.draw(this.posterBgImg)
}

4. 下载

点击下载合成图片

methods: {
    handleDownload(){
        if(this.poster){
            let a = document.createElement("a");
            a.setAttribute("download", "海报下载-"+(new Date().getTime()));
            a.href = this.poster
            a.click()
        }else{
            console.log("海报不存在,请重新生成!")
        }
    }
}

tips:不适用于微信浏览器,只能提示用户长按保存。

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
4年前
svg转png
svg转png网络上常用的方式有两种:1.直接转base64放到图片src进行显示,测试效果不佳,始终报方法问题。2.先转canvas,再转为png图,测试效果可以但svg透明背景到了canvas转换会变黑。推荐使用方法三:复制链接下载svg转png的jshttp://p8sv0x8g6.bkt.clouddn.com/saveSvgAs
Wesley13 Wesley13
4年前
UIWebView长按保存图片和识别图片二维码的实现方案(使用缓存)
0x00需求:长按识别UIWebView中的二维码,如下图长按识别二维码0x01方案1:给UIWebView增加一个长按手势,激活长按手势时获取当前UIWebView的截图,分析是否包含二维码。核心代码:略优点:流程简单,可以快速实现。不足:无法实现保存UIWebView中图片,如果当前We
Wesley13 Wesley13
4年前
java 代码生成分享海报,仅供参考
为了生成一个活动海报,不得不根据海报底图通过java代码手动生成一张海报(包含用户名,用户简介,商品图,商品价格,商品二维码宣传语等),通过千辛万苦后,终于画成功了,我强了但也秃了,这不是因为强而秃,而是我的同事告诉我,为什么不用通过网页htmlcss写出一张海报,然后java代码通过url保存为图片(?????)  我秃了
Stella981 Stella981
4年前
Python 生成个性二维码
1.1实验内容本课程通过调用MyQR接口来实现生成个人所需二维码,并可以设置二维码的大小、是否在现有图片的基础上生成、是否生成动态二维码。本课程主要面向Python3初学者。1.2知识点Python3基础MyQR库1.3效果截图1.3.1普通二维码!11.31
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
4年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
使用taro+canvas实现微信小程序的图片分享功能 | 京东云技术团队
业务场景二轮充电业务中,用户充电完成后在订单详情页展示订单相关信息,用户点击分享按钮唤起微信小程序分享菜单,将生成的图片海报分享给微信好友或者下载到本地,好友可通过扫描海报中的二维码加群领取优惠。使用场景及功能:微信小程序生成海报图片分享好友下载图片使用技