js 通过canvas生成带二维码的海报图

前言

h5移动端生成海报图,可长按图片保存或发送给朋友,或长按识别二维码。两种场景:第一种是生成项目分享海报图,通过背景图和地址生成的二维码合成一张海报图;第二种是通过页面生成商品海报图,页面有产品介绍信息,商户名称logo和商品详情页生成的二维码,把含有二维码的页面生成海报图。


一、背景图片和二维码合成一张图

示例:这里使用jquey实现的。

1.引入库

在script中引入jquery、qrcode.js生成二维码的插件。

2.使用步骤

准备一张海报背景图,html代码
js 通过canvas生成带二维码的海报图_第1张图片

长按海报转发,邀请好友助力点亮

#myCanvas {
    width: 300px;
    height: 532px;
}

生成海报图js
js 通过canvas生成带二维码的海报图_第2张图片

// 根据海报背景图和地址合成一张海报图
function createPoster(){
    // 二维码访问的地址拼接
    let  thref = location.protocol + "//"+location.hostname+"/flowerLantern/help.html?id="+voteId+"&orgId="+orgId+"&itemId="+itemIds;
    var canvas = document.getElementById("myCanvas");
    var ctx = canvas.getContext("2d"); 
    var devicePixelRatio = window.devicePixelRatio || 1,   
        backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1, 
        ratio = devicePixelRatio / backingStoreRatio;
    var qrcode = new QRCode("qrcode",{
        render: "canvas", //渲染方式指定canvas方式
        width: 72*ratio, //宽度 
        height: 72*ratio, //高度 
        typeNumber: -1, //计算模式
        text: thref, //任意内容 
        colorDark: "#000000",
        colorLight: "#ffffff",
        correctLevel: QRCode.CorrectLevel.H
    });
    var mycanvas1=document.getElementsByTagName('canvas')[0]; //获取网页中的canvas对象,这里是通过qrcode生成的二维码的canvas
    //将转换后的二维码img标签插入到html中
    var imgewm=convertCanvasToImage(mycanvas1); // 将二维码canvas生成图片
    $('#qrcode').html("");//移除已生成的避免重复生成
    $('#qrcode img').hide();
    var width = document.getElementById("myCanvas").clientWidth; //宽度 
    var height = document.getElementById("myCanvas").clientHeight; // 高度
    canvas.width = width*ratio;
    canvas.height = height*ratio;
    //首先画上背景图
    var img = new Image();
    img.src = './img/post.jpg'; // 背景图路径
    img.width = width;
    img.height = height;
    img.crossOrigin="*";
    img.onload = function() { //必须等待图片加载完成
        ctx.scale(ratio, ratio);
        ctx.drawImage(img, 0, 0, width, height); //绘制背景图像进行拉伸
        console.log(" ~ file: index.html ~ line 410 ~ createPoster ~ img", img)
        ctx.drawImage(imgewm,114,370,72,72); //绘制二维码
        //在ios上无法在画完之后取到整个画布内容,加了个settimeout
        setTimeout(function(){
            var srcImg = new Image();
            srcImg.src = canvas.toDataURL('images/png');   // 将合成的canvas转换成图片
            $('#h').html("");//移除已生成的避免重复生成
             $('#h').append(srcImg);// 将合成的图片渲染在页面上
             $('#h img').attr("width",'100%');
             $('#h img').attr("height",'100%');
             $('#qrcode').hide();
        },0)
    }
}

二、根据商品信息生成海报图

1.引入库

示例:这里使用vue实现的,通过npm安装相应的插件
cnpm install qrcodejs2 --save
cnpm install html2canvas --save
js 通过canvas生成带二维码的海报图_第3张图片

import QRCode from 'qrcodejs2';
import html2canvas from 'html2canvas'

2.实现:先生成二维码在页面上,然后页面通过canvas生成图片

这里是通过组件引入
js 通过canvas生成带二维码的海报图_第4张图片
子组件:
js 通过canvas生成带二维码的海报图_第5张图片

<div class="poster-top">
        <!-- 海报图生成的页面模块 -->
        <div id="posterHtml" v-show="true">
            <div class="postProduct">
              <!-- 商品图 -->
                <img :src="dataInfo.coverImg"/>
            </div>
            <!-- 内容 -->
            <div class="post-merch">
                <!-- 商户logo -->
                <img :src="merchantLogoUrl"/>
                <span>{{ realname}}&nbsp;&nbsp;为您推荐团兽兽好物</span>
            </div>
            <div class="post-content">
                <div class="post-content-left">
                <div class="post-product">{{ dataInfo.title.split('#')[0] }}</div>
                <div class="post-price">
                    <span class="price"><span class="rmb"></span>{{ dataInfo.salePrice}}&nbsp;&nbsp;&nbsp;</span>
                    <!-- <p class="stock"> <span class="stock">库存:{{ dataInfo.stockCount }}</span></p> -->
                </div>
                </div>
                <div class="qrcode-wrapper">
                <!-- 二维码 -->
                <div id="qrcodeImg" class="qrcode"></div>
                <p class="ewm-text">长按识别二维码</p>
                </div>
            </div>
        </div>
        <!-- 存放最后生成的海报图 -->
        <div id="result"></div>
     </div>

js

// 生成二维码
createCode(){
      var codeMd5 = this.domain+'/'+this.dataInfo.url;
      console.log("md5?",codeMd5);
      let qrcode = new QRCode('qrcodeImg', {
        width: 70,
        height: 70,
        // text: "https://www.baidu.com",
        text: codeMd5, // 二维码地址
        colorDark : "#000",
        colorLight : "#fff",
      })
    },
    // 生成海报图
    createPoster() {
      console.log(" ~ file: poster.vue ~ line 91 ~ createPoster ~ createPoster")
      // 生成海报
      const vm = this
      const domObj = document.getElementById('posterHtml');
      var width = domObj.offsetWidth; //获取dom 宽度

      var height = domObj.offsetHeight; //获取dom 高度
      // var canvas = document.createElement("canvas"); //创建一个canvas节点
      // var scale = window.devicePixelRatio; //定义任意放大倍数 支持小数
      // // var scale = 2; //定义任意放大倍数 支持小数
      // canvas.width = width * scale; //定义canvas 宽度 * 缩放      
      // canvas.height = height * scale; //定义canvas高度 *缩放      
      // canvas.style.width = width + "px";      
      // canvas.style.height = height + "px";      
      // canvas.getContext("2d").scale(scale,scale); //获取context,设置scale

      window.pageYOffset = 0;
      document.documentElement.scrollTop = 0
      document.body.scrollTop = 0;
      const toast1 = this.$toast.loading({
                duration: 0,       // 持续展示 toast
                forbidClick: true, // 禁用背景点击
                loadingType: 'spinner',
                message: '海报生成中'
            });
      (window.html2canvas || html2canvas)(domObj, {
        // dpi: window.devicePixelRatio * 2,

        
        useCORS: true, //是否尝试使用CORS从服务器加载图像
        allowTaint: false, //允许跨域图片.
        // logging: false,
        // letterRendering: true,
        // canvas:canvas, //自定义 canvas
        width: domObj.offsetWidth, //为了解决安卓手机截图后出现白边的问题
        height: domObj.offsetHeight, //为了解决安卓手机截图后出现白边的问题
        // scale:  window.devicePixelRatio , // 添加的scale 参数
        scale:2,
        onclone(doc) {
          // let e = doc.querySelector('#posterHtml')
          // e.style.display = 'block'
        },
        onrendered:function(canvas){
        console.log(" ~ file: poster.vue ~ line 126 ~ createPoster ~ canvas", canvas)
          // vm.posterImg = canvas.toDataURL('image/png',1.0);
          // var img = document.createElement("img");
          // img.src=vm.posterImg;
          // img.style.width = '100%';
        }
        
      }).then(function(canvas) {
        toast1.clear();
        // 在微信里,可长按保存或转发
        vm.posterImg = canvas.toDataURL('image/png',1.0)
        console.log(" ~ file: view.vue ~ line 166 ~ createPoster ~ vm.posterImg", vm.posterImg)
        // var img = document.createElement("img");
          // img.src=vm.posterImg;
          // img.style.width = '100%';
          var img = new Image();
          img.src=vm.posterImg;
          img.id = 'posterImgBae64';
          var result = document.getElementById("result");
          result.appendChild(img); // 页面上渲染生成的海报图
          img.style.width = '100%';
          let e = document.getElementById('posterHtml'); // 原来的页面结构隐藏
          e.style.display = 'none';
        
      })
    },

调用方法
js 通过canvas生成带二维码的海报图_第6张图片

if(this.dataInfo.url){
        this.createCode(); // 生成二维码
        setTimeout( ()=> {
         this.createPoster(); //生成海报
        },100);
}

效果图
js 通过canvas生成带二维码的海报图_第7张图片


总结

两种业务场景生成海报图,都是用canvas生成图片。生成商品海报图时商户logo图模糊,文字模糊,调试像素比,通过scale调整。

你可能感兴趣的:(vue,javascript,vue.js)