Vue.js结合Canvas制作二维码和图片的合成(html2canvas + Canvas2Image)--整理

之前写过一篇关于二维码和图片合成的博文,但是存在一些问题,本篇是本人整理最后在项目中使用的。

建议:如果是单张背景图或者是多张背景图且二维码在同一位置的话,建议直接在后台合成分享图直接给前端返回即可,我这次项目需求是多张背景图并且二维码的位置都不同,后台不方便处理,所以直接前端来处理了。

需求背景:

 分享图片,图片中含有自己分享链接生成的二维码!!

大体思路:

  • 第一步、将自己的分享码或其他字段传给后台,后台返回Base64格式的二维码图片;(至于为什么要使用Base64格式,如果返回其他格式的图片会出现二维码加载不出来的情况)
  • 第二步、二维码放在背景图的指定位置,再合成分享图片;

npm安装:

1.npm install html2canvas --save  //html转canvas

2.npm install canvas2image --save  //canvas转图片

页面引入:

import html2canvas from 'html2canvas';

import Canvas2Image from 'canvas2image';

html:

<!-- 分享 -->
<template>
    <div class="container share">
        <!-- 换一张按钮 -->
        <div @click="shareChange" class="share_change" v-show="changeShow">换一张</div>
        <!-- 背景列表 -->
        <div class="mark" :class="markShow?'':'mark_position_left'">
            <p>--请选择生成图片--</p>
            <div class="mark_item" v-for="(item,index) in imgUrls" :key="index" @click="getBgImg(item)">
                <img :src="item.imgurl" alt="">
            </div>
        </div>
        <!-- 生成图片的DOM -->
        <div class="share_box" ref="box">
            <div class="img-box">
                <!-- 背景图 -->
                <img class="shareBg" @load="bgImgload" :src="bgImg" alt="">
                <!-- 二维码 -->
                <div class="shareQr" :class="imgUrls[(pid > 0 ? pid : 1) - 1].isClass">
                    <img @load="qrcodeLoad" :src="qrCodeUrl" alt="">
                </div>
            </div>
        </div>
        <!-- 存放合成的图片 -->
        <div class="share-img" id="shareImg"></div>
    </div>
</template>

js:

<script>
import html2canvas from 'html2canvas';
import Canvas2Image from 'canvas2image';
export default {
    data () {
        return {
            changeShow:false,
            markShow:true,
            qrCode:false,
            pid:0,
            imgUrls:[
                {pid:1,imgurl:require("@/assets/images/share/share1.jpeg"),isClass:'shar1'},
                {pid:2,imgurl:require("@/assets/images/share/share3.jpeg"),isClass:'shar2'},
                {pid:3,imgurl:require("@/assets/images/share/share4.jpg"),isClass:'shar3'},
                {pid:4,imgurl:require("@/assets/images/share/share5.jpg"),isClass:'shar4'},
                {pid:5,imgurl:require("@/assets/images/share/share6.jpg"),isClass:'shar5'},
                {pid:6,imgurl:require("@/assets/images/share/share7.jpg"),isClass:'shar6'},
                {pid:7,imgurl:require("@/assets/images/share/share8.jpg"),isClass:'shar7'},
                {pid:8,imgurl:require("@/assets/images/share/share9.jpg"),isClass:'shar8'},
                {pid:9,imgurl:require("@/assets/images/share/share10.jpg"),isClass:'shar9'}
            ],
            bgImg:'',
            qrCodeUrl:'',
            invitationCode:'',
            timer:null,
        }
    },
    created() {
        //邀请码
        this.invitationCode = this.$route.query.invitationCode;
        //获取二维码
        this.getQrCodeBase64();
    },
    mounted() {},
    
    methods: {
        //换一张
        shareChange(){
            this.changeShow = !this.changeShow;
            document.getElementById('shareImg').innerHTML = '';
            this.markShow = true;
        },
        //获取二维码
        getQrCodeBase64(){
            let that = this;
            that.$http.get('user/getInviteQrCode',{
                parmas:{
                    code:that.invitationCode
                }
            }).then(res => {
                if(res && res.data.code == 0){
                    that.qrCodeUrl = res.data.data;
                }
            })
        },
        //获取背景图
        getBgImg(e){
            let that = this;
            that.changeShow = true;
            that.markShow = false;
            if(e.pid == that.pid){
                //前一张加载过
                that.bgImgload();
            }else{
                //未加载过
                that.pid = e.pid;
                that.bgImg = e.imgurl;
            }
        },
        //二维码是否渲染完毕
        qrcodeLoad(){
            this.qrCode = true;
        },
        //背景图加载完回调
        bgImgload(){
            this.$indicator.open({
                text: '正在生成图片...',
                spinnerType: 'fading-circle'
            });
            this.creatImg();
        },
        //生成图片
        creatImg(){
            let that = this;
            if(that.qrCode){
                // 已经生成二维码
                clearInterval(this.timer)
                let element = that.$refs.box;
                html2canvas(element,{allowTaint:true,taintTest: false}).then(function(canvas) {
                    document.getElementById('shareImg').appendChild(Canvas2Image.convertToPNG(canvas));
                    that.$indicator.close(); 
                    that.$toast({
                        message: '图片已生成,长按保存分享给你的好友吧',
                        position: 'middle',
                        duration: 2000
                    });   
                });
            }else{
                that.timer = setInterval(() => {
                    that.creatImg()
                },300)
            }
        }
    },
    destroyed () {
        this.$indicator.close(); 
        clearInterval(this.timer)
    }
}

</script>

css:

.share {
    width: 100%;
    height: calc(100% - .6rem);
    background: #fff;
    .share_change {
        font-size: 14px;
        padding: .04rem .1rem;
        color: #fff;
        background: rgba(0, 0, 0, .4);
        border-radius: 100px;
        position: fixed;
        top: 1.5rem;
        right: .1rem;
    }
    .mark {
        width: 96%;
        height: 100%;
        margin: 0 auto;
        overflow-y: scroll;
        p {
            font-size: 14px;
            text-align: center;
            margin: .1rem 0;
            color: #888888;
        }
        .mark_item {
            width: 40%;
            margin: 0 5%;
            margin-bottom: .2rem;
            box-shadow: 1px 1px 1px 2px #ccc;
            float: left;
        }
    }
    .mark_position_left {
        position: fixed;
        top: 0;
        left: -100%;
    }
    .share_box {
        width: 100%;
        position: fixed;
        top: 0;
        left: -100%;
    }
    .img-box {
        position: relative;
        .shareBg {
            z-index: 3;
        }
        .shareQr {
            position: absolute;
            z-index: 5;
        }
        .shar1 {
            width: .49rem;
            height: .49rem;
            top: 6rem;
            left: .86rem;
        }
        .shar2 {
            width: .49rem;
            height: .49rem;
            top: 5.7rem;
            right: .24rem;
        }
        .shar3 {
            width: .75rem;
            height: .75rem;
            top: 4.88rem;
            right: .21rem;
        }
        .shar4 {
            width: .66rem;
            height: .66rem;
            top: 4.98rem;
            left: .17rem;
        }
        .shar5 {
            width: .6rem;
            height: .6rem;
            top: 5.05rem;
            left: .09rem;
        }
        .shar6 {
            width: .6rem;
            height: .6rem;
            top: 5.1rem;
            left: 1.56rem;
        }
        .shar7 {
            width: .64rem;
            height: .64rem;
            top: 4.69rem;
            left: 1.12rem;
        }
        .shar8 {
            width: .75rem;
            height: .75rem;
            top: 2.73rem;
            left: 1.5rem;
        }
        .shar9 {
            width: .65rem;
            height: .65rem;
            top: 2.72rem;
            left: 1.54rem;
        }
    }
}

 

©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页