In vuejs, html2canvas uses the background image and QR code poster image to save it to a picture to generate a poster and download it.

In many projects, QR codes and background images are used to generate promotional images for posters. The method of implementation is to draw the canvas onto one image and then download it. The techniques of html2canvas are not explained here.

QR code and background image for positioning.

In traditional situations, such functions often rely on background synthesis of images or on-end implementation, but the web side itself also has independent solutions. The canvas tag that has the image generation function in the Web can use the toDataUrl() API in canvas to get the base64 data URI of the current canvas content, which is the image data.

toDataUrl() api description

Therefore, the most direct idea is to draw personalized content on canvas and use API to convert it into pictures. But this is still too cumbersome and requires dealing with a large number of drawing APIs, which is not intuitive and easy to reuse. The most intuitive thing on the web side is the DOM content. If the DOM content can be quickly converted into canvas, and then converted from canvas into pictures, the above functions can be quickly realized. Fortunately, we have a powerful tool-html2canvas.

html2canvas is a set of open source tools developed by individuals, used to convert dom content drawn with html tags into canvas.

Through an asynchronous process, the HTML image is converted into canvas, and then the canvas api is called to obtain the dataURL. Finally, the data URL is assigned to the src attribute of the img tag to generate a complete image.

We focus on the calling parameters

canvas

The canvas container used for conversion. Note that the container can be written to the DOM in advance, or it can be created dynamically as shown in the above code. There is no difference between the two calling methods. If it is created dynamically and is not linked to the DOM tree, the container will be invisible throughout the process. Therefore, this method is more recommended for single one-time image generation.

<div class="big_codebox ">
<h4 class=" font-20 font-bold padd01">二维码海报</h4>
<div class="big_code bot_top">
  <div class="code">
    <template>
      <div>
        <!-- ref="box" 是 需要保存图片的div盒子 -->
        <div ref="box" id="shareImg">
          <img :src='require("../../assets/images/user/tgbg.png")' alt="">// 背景图
          <div class="imgs2">
            <img :src='qrmcodeSrc' alt="" class="codeimg"> //二维码
            <p class="codeimgtxt">邀请码:{
   
   {tjCode}}</p>  //二维码上的文字
          </div>
        </div>
        <!--生成的合成图片-->
        <!-- <img :src="imgUrl" alt=""> -->
        <!-- <img :src="'data:image/jpeg;base64,' + downloadUrl"/> -->
      </div>
    </template>
    <el-button type="primary" class="m20" @click="saveImage('box','推广二维码')">点击按钮保存二维码海报,去社交媒体推广</el-button>
  </div>
</div>
</div>

The // comments in the code need to be deleted, here to facilitate everyone's understanding. You need to use the html2canvas tool here.

import VueQr from "vue-qr";
import html2canvas from 'html2canvas';
data() {
    TGurl:'',
    myMlink:'',
    tjCode:'',
    imgUrl:'',
    shopPic:'',
    rowData:'',
    downloadUrl:'',
    divText:'box',
    imgText:'好友推广二维码'
}

The idea and part of the code are as follows:

1. Lay out the image style and add the ref="" attribute to the div that needs to be saved.

2. Look at the code

this.test();//Get the database64 url. After getting the parameters, use this method directly

test(dataUrl,id){
        // console.log(dataUrl, id);
        this.qrmcodeSrc=dataUrl;
        // console.log(this.qrmcodeSrc);
        this.draw()
    },
draw(){
      if(this.qrmcodeSrc) return
        var that = this;
        if(this.qrmcodeSrc) return
        html2canvas(that.$refs.box).then(function(canvas) {
          that.imgUrl = canvas.toDataURL()//将canvas转为base64图片(eg. data:image/png;base64,ijskjlkj)
        });
    },
//图片转换格式的方法 直接使用就好 不需要知道为什么
dataURLToBlob(dataurl) {
  let arr = dataurl.split(',');
  let mime = arr[0].match(/:(.*?);/)[1];
  let bstr = atob(arr[1]);
  let n = bstr.length;
  let u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], { type: mime });
},
/*保存图片的方法(即按钮点击触发的方法)
第一个参数为需要保存的div的id名
第二个参数为保存图片的名称 */
saveImage(divText, imgText) {
  let canvasID = this.$refs[divText];
  let that = this;
  let a = document.createElement('a');
  html2canvas(canvasID).then(canvas => {
    let dom = document.body.appendChild(canvas);
    dom.style.display = 'none';
    a.style.display = 'none';
    document.body.removeChild(dom);
    let blob = that.dataURLToBlob(dom.toDataURL('image/png'));
    a.setAttribute('href', URL.createObjectURL(blob));
    //这块是保存图片操作 可以设置保存的图片的信息
    a.setAttribute('download', imgText+this.tjCode + '.png');//二维码图片名称
    document.body.appendChild(a);
    a.click();
    URL.revokeObjectURL(blob);
    document.body.removeChild(a);
  });
},

Share a case code


<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
	<!-- <meta http-equiv="Content-Security-Policy" content="script-src 'self' *.url.cn *.idqqimg.com *.qq.com *.gtimg.cn 'unsafe-inline' 'unsafe-eval';">      -->
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	<meta name="apple-mobile-web-app-capable" content="yes" />
	<meta name="apple-mobile-web-app-status-bar-style" content="black" />
	<meta name="Copyright" content="Tencent" />
	<meta name="format-detection" content="telephone=no" />
	<title></title>
    <script></script>
    <style>
		/*commonArea,手Q中H5页面通用css基础样式区域*/
    	html,body, div, p, ol, ul, li, table, tbody, tr, td,
        form, h1, h2, h3, h4, h5, dl, dt, dd, img, iframe, header, nav,
        section, article, footer, figure, figcaption, menu, a, p,button {padding: 0;margin: 0; -webkit-user-select: none; -moz-user-select: none; -webkit-text-size-adjust: none;-webkit-touch-callout: none;}
        textarea,input{padding: 0;margin: 0;}
        html ,body{ width: 100%; height: 100%;}
        body { font-size: 62.5%; font: 16px "Helvetica Neue", Helvetica, STHeiTi, "\5FAE\8F6F\96C5\9ED1", sans-serif; min-width: 320px; margin: 0 auto;background:#ece0c1}
        em{ font-style: normal;}
        a, span { text-decoration: none;display: inline-block;}
        a:link, a:visited{text-decoration:none;}
        a,button{outline: none; -webkit-tap-highlight-color:rgba(0,0,0,0);}
        button{border:none; background: transparent;}
		li {list-style: none;}
        body{
            text-align: center;
        }
        #content{
            position: relative;
            margin:auto;
			margin-top:50px;
            width:588px;
            height:849px;
            box-sizing: border-box;
            overflow:hidden;
        }
        .letter-content{
            background-position: 0 0;
            background-repeat: no-repeat;
            background-size: 100% 100%;
            position: absolute;
            top:0;
            left:0;
            width:588px;
            height:849px;
        }
        .copyImage{
            width: 100%;
            position: absolute;
            top:0;
            left:0;
            z-index: 10002;
            width:588px;
            height:849px;
            opacity:0;
        }
        .letter-title{
            position: absolute;
            top: 420px;
            left: 0;
            color: #d9feec;
            text-shadow: 0 0 0.4em #348132, 0 0 0.4em #348132;
            text-align: center;
            width:100%;
            font-size:48px;
            z-index: 10001;
        }
        .letter-bg{
            width: 588px;
            height: 849px;
            position: absolute;
            top: 0;
            left: 0;
            z-index:10000;
            background-image: url("./bg.jpg");
            background-size: 100% 100%;
            /* box-shadow: #348132 10px 10px 10px; */
        }
        button{
            font-size:24px;
            border:1px solid gray;
            padding:10px 0;
            margin:10px;
            width:200px;
        }
        button:active{
            background:#fafafa;
        }
    </style>
    </head>
    <body ontouchstart="">
        <div id="content">
            <img src="" class="copyImage">
            <div class="letter-content" id="letter">
                <p class="letter-title">1970:0:0</p>
                <div class="letter-bg">
                    <!-- <img id="letter-bg-img" src="https://sqimg.qq.com/qq_product_operations/qim/film/share/pink_letter.png"> -->
                </div>
                <div class="ecode"></div>
            </div>
        </div>
        <button id="change-style">圆角透明</button>
        <button id="save-local">保存到本地</button>
        <a id="dl-hidden" style="display:none;"></a>
    </body>
    <script src="./zepto.js"></script>
    <script src="./html2canvas.min.js"></script>
    <script>
        window.onload = function(){
        var IMAGE_URL;
        function takeScreenshot(){
            var shareContent = document.getElementById('letter');//需要截图的包裹的(原生的)DOM 对象
            var width = shareContent.offsetWidth; //获取dom 宽度
            var height = shareContent.offsetHeight; //获取dom 高度
            var canvas = document.createElement("canvas"); //创建一个canvas节点

            var scale = 2; //定义任意放大倍数 支持小数
            canvas.width = width * scale; //定义canvas 宽度 * 缩放
            canvas.height = height * scale; //定义canvas高度 *缩放
            canvas.getContext("2d").scale(scale,scale); //获取context,设置scale

            // var rect = shareContent.getBoundingClientRect();//获取元素相对于视察的偏移量
            // canvas.getContext("2d").translate(-rect.left,-rect.top);//设置context位置,值为相对于视窗的偏移量负值,让图片复位
            var opts = {
                scale:scale, // 添加的scale 参数
                canvas:canvas, //自定义 canvas
                logging: true, //日志开关
                width:width, //dom 原始宽度
                height:height, //dom 原始高度
                backgroundColor: 'transparent',
            };
            html2canvas(shareContent, opts).then(function (canvas) {
                IMAGE_URL = canvas.toDataURL("image/png");
                $('.copyImage').attr('src',IMAGE_URL);
            })
        }

        function dataURLtoBlob(dataurl) {
            var arr = dataurl.split(','),
                mime = arr[0].match(/:(.*?);/)[1],
                bstr = atob(arr[1]),
                n = bstr.length,
                u8arr = new Uint8Array(n)
            while (n--) {
                u8arr[n] = bstr.charCodeAt(n)
            }
            return new Blob([u8arr], { type: mime })
        }

        function downloadBase64(dataUrl, filename) {
            var imageFile, href
            // const downloadLink = document.createElement('a')
            var downloadLink = document.getElementById('dl-hidden')
            try {
                var blob = dataURLtoBlob(dataUrl)
                    var href = window.URL.createObjectURL(blob)
                    downloadLink.download = filename
                    downloadLink.href = href
                    downloadLink.click()
            } catch (err) {
            } finally {
                if (href) {
                    window.URL.revokeObjectURL(href)
                }
                // downloadLink.remove()
            }
        }

				$(".letter-title").text(new Date().toLocaleString());
				takeScreenshot();
				var curStyle=0;
				$("#change-style").click(function(e){
						takeScreenshot();
						if(curStyle==0){
								$(".letter-content").attr("style","opacity:0.8;");
								$(".letter-bg").attr("style","border-radius:50px;");
								$("#change-style").text("普通");
								curStyle=1;
						}else{
								$(".letter-content").attr("style","opacity:1;");
								$(".letter-bg").attr("style","border-radius:0;");
								$("#change-style").text("圆角透明");
								curStyle=0;
						}
				})
				$("#save-local").click(function(e){
						downloadBase64(IMAGE_URL, '合成图.png')
				})
    }
</script>
</html>

Friends who don’t understand can follow the QR code for discussion!

Okay, if you have any questions you don’t understand, you can follow my personal WeChat official account and communicate with me.

At the same time, you can also receive front-end learning materials! Welcome everyone to pay attention. Join me to discuss, learn and exchange H5 front-end development.

Guess you like

Origin blog.csdn.net/u012118993/article/details/99092277