一. 需求背景

长按分享图片,图片中含有自己分享链接生成的二维码,需要把二维码和背景图合成一张海报,项目需求是循环生成多张海报
在这里插入图片描述

二. canvas画布的生成条件

  1. 要生成画布的html元素不能是隐藏状态。如果不想页面显示出来的话,可以给个 margin-top: -999999999px;
  2. 生成画布方法需要在页面渲染结束之后执行。

三. 如何生成单个画布 ?

思路:

  1. 根据自己的分享链接通过vue-qr生成一个二维码;

  2. 获取要生成画布的容器,比如通过id或者that.$refs获取页面元素外层的div

  3. 调用指定方法生成,生成出来的是base64的图片

  4. 通过canvas.toDataURL(“image/png”); 将canvas转为base64图片(eg. data:image/png;base64,ijskjlkj)

  5. 赋值给img标签的src即可

npm安装

npm install vue-qr --save  //生成二维码
npm install html2canvas --save   //html转canvas

页面引入

import vueQr from 'vue-qr'
import html2canvas from "html2canvas";

生成的二维码和背景图的具体定位,可通过css控制,这块代码忽略。

<template>
        <div>
        <!-- 生成图片的DOM -->
            <div ref="box">
                <!-- 背景图 -->
	           <img :src="item.img" class="img" />
	           <!-- 二维码 -->
               <div style="width:60px;height:60px;position:absolute;right:5px;bottom:22px">
                 <vue-qr :text="invite_url" :size="500"></vue-qr>
               </div>
            </div>
            <!--存放合成的图片-->
            <img :src="imgUrl" alt="">
       </div>
</template>
<script>
import vueQr from 'vue-qr'
import html2canvas from 'html2canvas';
export default {
        data() {
            return{
                    invite_url: "https://www.baidu.com/"
                    imgUrl:''
            }
        },
        methods:{
                draw(){
                    var that = this;
                    html2canvas(that.$refs.box).then(function(canvas) { //第一个参数是需要生成截图的元素
                      that.imgUrl = canvas.toDataURL()//将canvas转为base64图片(eg. data:image/png;base64,ijskjlkj)
                  });
                }  
        },
        mounted(){
            this.draw()
        }
    };
</script>

四. 循环生成多个画布

思路:

// 1.循环的时候,根据索引生成不同的id
  :id="`imgContainer_${index}`"
  v-for="(item, index) in currentImgList"
  
// 2.获取页面元素的时候,也可以采用循环的方式,先拼接id
  for (var i = 0; i < this.currentImgList.length; i++) {
        var key = "imgContainer_" + i; //这里的i也是从0开始的,跟html中的id对应起来
        // imgContainer_0,imgContainer_1 这种
        var box = document.getElementById(key);
        
// 3.循环中根据id生成画布,push到一个数组即可
    	url = canvas.toDataURL("image/png");
        img_arr.push({ img: url });
        
// 4.最后输出img_arr 这个数组到页面上即可
          this.canvasImgList = img_arr;

具体代码
html

<template>
<div class="myself">
  <div class="share" ref="parent_wrapper" v-show="is_share">
      <van-icon
        name="cross"
        color="#fff"
        size="20"
        class="closeIcon"
        @click="cancel()"
      />
      <div class="info">
        <p>长按保存或者截图分享</p>
      </div>
      <!--存放合成的图片;这个div因为固定在下方的第一个按钮不需要canvas生成海报-->
     <div
        class="wrapper_box"
        style="min-height:100vh;"
        ref="wrapper"
        v-if="is_convas"
      >
        <div class="content" ref="wrapperChild">
          <div
            v-for="(item, index) in currentImgList"
            :key="index"
            class="imgItem"
          >
            <img :src="item.img" class="img" style="margin: 0 10px;" />
          </div>
        </div>
      </div>
 
       <div
        class="wrapper_box"
        style="min-height:100vh;
        "
        ref="wrapper"
        v-else
      >
        <div class="content" ref="wrapperChild">
        <!-- 生成图片的DOM -->
          <div
            :id="`imgContainer_${index}`"
            v-for="(item, index) in currentImgList"
            :key="index"
            class="imgItem"
          >
            <!-- 循环的背景图 -->
            <img :src="item.img" class="img" />
            <!-- 生成的二维码 -->
            <div
              style="width:64px;height:64px;position:absolute;right:10px;bottom:22px"
            >
              <vue-qr :text="invite_url" :size="500"></vue-qr>
            </div>
          </div>
        </div>
      </div>
      <p class="tips">
        点击右上角选择【发送给朋友】或【分享到朋友圈】 邀请朋友一起成为合伙人。
      </p>
    </div>
    <div class="page_bottom">
      <div class="zzb_share" @click="go_zzb">按钮1</div>
      <div class="zzb_share partner_share" @click="go_partner">按钮2</div>
    </div>
</div>
</template>

js部分

<script>
import indexApi from "@/api/index.js";
import BScroll from "better-scroll";
import vueQr from "vue-qr";
import html2canvas from "html2canvas";
import { Popup, Button, Icon, Swipe, SwipeItem } from "vant";

export default {
  data() {
    return {
      zzbList: [
        { img: require("../../assets/image/zzb_1.png") },
        { img: require("../../assets/image/zzb_2.png") },
        { img: require("../../assets/image/zzb_3.png") }
      ],
      partnerList: [
        { img: require("../../assets/image/partner_1.jpg") },
        { img: require("../../assets/image/partner_2.jpg") },
        { img: require("../../assets/image/partner_3.jpg") }
      ],
      invite_url: "https://www.baidu.com/"
      currentImgList: [],
      canvasImgList: [],
      is_share: false,
      is_convas: false,
    };
  },
 
  mounted() {
    //mounted 里面 初始化数组,初始化scroll
    this.currentImgList = this.partnerList;
    let authTimeTimer = setTimeout(() => {
      if (this.invite_code) {
        this.init_partner();
      }
      clearTimeout(authTimeTimer);
    }, 500);
  },
  methods: {
    cancel() {
      this.is_share = false;
    },
    go_partner() {
      this.$refs.parent_wrapper.classList.remove("code_p");
      this.currentImgList = this.canvasImgList;
      this.is_share = true;
      this.is_convas = true;  //展示只有合成图片的div
      this.slide_x(); //better-scroll的滑动组件,忽略即可
    },
    init_partner() {
      this.is_share = true;
      this.is_convas = false;  //展示有背景图,二维码的div
      this.$refs.parent_wrapper.classList.add("code_p");
      //this.currentImgList = this.partnerList;
      // 生成convas;
      let authTimeTimer = setTimeout(() => {
        this.createCanvas();
        clearTimeout(authTimeTimer);
      });
    },
    createCanvas() {
      var img_arr = [];
      for (var i = 0; i < this.partnerList.length; i++) {
        var key = "imgContainer_" + i;
        // console.log(key);
        var box = document.getElementById(key);
        let url = "";
        //第一个参数是需要生成截图的元素,第二个是自己需要配置的参数,宽高等
        html2canvas(box, {
          backgroundColor: null,
          dpi: 192, // 将分辨率提高到特定的dpi,默认值为96
          scale: 2, // 用于渲染的比例尺。默认为浏览器设备像素比率。默认值是1,手机端设置成2
          useCORS: true // 如果截图的内容里有图片,可能会有跨域的情况,加上这个参数,解决文件跨域问题
        }).then(canvas => {
          url = canvas.toDataURL("image/png");
          img_arr.push({ img: url });
        });
      }
      this.canvasImgList = img_arr;
      this.is_convas = true;  //展示只有合成图片的div
    }
  },
.code_p {
  // 这个是让 默认得元素的隐藏,并且能 截图海报 截取到的方法
  margin-top: -999999999px;
}

关于canvas刚接触了解不太多,欢迎大家指正,一起进步~

Logo

前往低代码交流专区

更多推荐