vue 生成二维码海报并进行微信分享

插件:Vue Canvas Poster 

网址:Vue Canvas Poster

1、安装

cnpm i vue-canvas-poster --save

2、使用

<template>
  <div class="share wh100">
    <navBar title="邀请好友" :leftArrowFlag="true" />
    <div class="content">
      <h2>邀请亲友加入亲友团</h2>
      <p>
        邀请亲友加入后,可与您一起编写逝者生平故事,留言、上传照片、跟您一起完善逝者信息、共同缅怀
      </p>
      <div class="share_item">
        <h3>方法一:长按海报发送朋友邀请加入</h3>
        <div class="item_content">
          <vue-canvas-poster
            :widthPixels="1000"
            :painting="painting"
            @success="success"
            @fail="fail"
          ></vue-canvas-poster>
          <div class="poster_box">
              <img v-if="showPoster" class="poster_img" :src="detail.posterImg" alt="" />
          </div>
        </div>
      </div>
      <div class="share_item">
        <h3>方法二:点击发送链接邀请亲朋加入</h3>
        <div class="item_content">
          <div class="large_btn" @click="wxShare"><span>点击发送链接邀请亲朋加入</span></div>
        </div>
      </div>
    </div>
    <van-overlay class="overlay_box" :show="show" @click="show = false">
        <div class="mask_content"  @click="show = false">
                <img class="arrow" src="http://****/files/app/download/pic/arrow.png" alt="">
                <div class="mask_main">
                    <div class="main_item">
                        <div class="item_tip"><span>1</span></div>
                        <div class="item_test">
                            <span>点击右上角</span>
                            <div class="item_btn">
                                <span>. . .</span>
                            </div>
                            <span>按钮</span>
                        </div>
                    </div>
                    <div class="main_item">
                        <div class="item_tip"><span>2</span></div>
                        <div class="item_test">
                            <span>将本页面分享给好友</span>
                            
                        </div>
                    </div>
                </div>
            </div>
    </van-overlay>
  </div>
</template>
<script>
import navBar from "@/components/navBar";
import { VueCanvasPoster } from "vue-canvas-poster";
import sdk from "@/utils/wxShare"
import {getShareData} from '@/api/memorialHall'
export default {
  data() {
    return {
      painting:null,
      showPoster:false,
      show:false,//显示隐藏
      detail: {
        posterImg:null
      },
    };
  },
  components: {
    navBar,
    VueCanvasPoster,
  },
  created() {
    console.log(this.detail.posterImg, "分享");
    this.getData(this.$route.params.id)
  },
  mounted() {
    
  },
  methods: {
    async getData(id) {
      let params={
        id
      }
      let res= await getShareData(params)
      console.log(res,'000')
      if(res.code!='2000'){
        this.$toast.fail(res.msg)
        return 
      }
      this.detail=res.data;
    
      this.ininShare(res.data)
     this.initPoster(res.data)
    },
    ininShare(data){
      var ua = window.navigator.userAgent.toLowerCase();
      if (ua.match(/MicroMessenger/i) == 'micromessenger') {
          let obj={
              title: `${data.deadName}的纪念馆`,
              des:`${data. biography}`,
              linkurl: `http://**************/memorialHall/${data.id}`,//分享链接
              img: `${data.deadPortraitUrl}`,	
          }
          // let url = encodeURIComponent(location.href.split('#')[0]);
          let url = location.href.split('#')[0];
          sdk.getJSSDK(url, obj)
      }else{

      }
    },
    initPoster(data){
         this.painting = {
        width: "275px",
        height: "365px",
        borderRadius: "5px",
        background: `${data.captionUrl}`,
        views: [
          {
            type: "image",
            url: `${data.deadPortraitUrl}`,
            css: {
              top: "20px",
              left: "107.5px",
              borderRadius: "30px",
              width: "60px",
              height: "60px",
            },
          },
          {
            type: "text",
            text: `${data.deadName}的纪念馆`,
            css: {
              top: "90px",
              fontSize: "14px",
              left: "90px",
              color: "#fff",
              textAlign: "center",
            },
          },
          {
            type: "text",
            text: `${data.birthday}-${data.deathday}`,
            css: {
              top: "110px",
              fontSize: "14px",
              left: "60px",
              color: "#fff",
              textAlign: "center",
            },
          },
          {
            type: "qrcode",
            content: `http://****/memorialHall/${data.id}`,
            css: {
              background: "#fff",
              padding: "10px",
              width: "100px",
              height: "100px",
              left: "90px",
              top: "170px",
              borderWidth: "10px",
              borderRadius: "1px",
              borderColor: "#fff",
            },
          },
          {
            type: "text",
            text: "扫码查看在线纪念馆",
            css: {
              bottom: "50px",
              fontSize: "14px",
              left: "80px",
              color: "#fff",
              textAlign: "center",
            },
          },
        ],
      };
      
    },
    success(src) {
      
      this.detail.posterImg = src;
      this.showPoster=true
    },
    fail(err) {
      console.log("fail", err);
    },
    wxShare(){
      this.show=true
    }
  },
};
</script>
<style lang="scss" scoped>
.share {
  display: flex;
  flex-direction: column;
  .content {
    flex: 1;
    padding: 0.12rem 0.37rem;
    // background-color: #3e3e3e;
    h2 {
      font-size: 16px;
      line-height: 0.23rem;
      font-weight: 600;
      margin-bottom: 0.07rem;
    }
    p {
      font-size: 14px;
      line-height: 0.2rem;
      color: $lightBlack;
      margin-bottom: 0.05rem;
    }
    .share_item {
      margin-bottom: 0.1rem;
      h3 {
        font-size: 16px;
        line-height: 0.23rem;
        font-weight: 600;
        margin-bottom: 0.07rem;
      }
      .item_content {
        display: flex;
        flex-direction: column;
        align-items: center;
        .poster_box {
             width: 2.75rem;
          height: 3.65rem;
         img{
             width: 100%;
             height: 100%;
         }
        }
      }
    }
    
  }
}
.overlay_box{
  .mask_content{
            padding:1rem 0.5rem;
            font-size: 14px;
            color: #fff;
        }
        .main_item{
            display: flex;
            align-items: center;
            margin-bottom: 0.2rem;
        }
        .item_test{
            display: flex;
            align-items: center;
        }
        .item_tip{
            width: 0.2rem;
            height: 0.2rem;
            border-radius: 50%;
            background: crimson;
            text-align: center;
            line-height: 0.2rem;
            margin-right: 0.15rem;
        }
        .item_btn{
            padding:0.05rem 0.1rem;
            text-align: center;
            height: 0.3rem;
            background: #282D32;
            border-radius: 0.05rem;
            margin:0 0.1rem;
        }
        .item_btn span{
            line-height: 0.2rem;
        }
        .arrow{
            position: absolute;
            right:0.2rem;
            top:0.2rem;
            display: block;
            width: 1rem;
            z-index: 6;
        }
}
</style>

wxShare.js

import {wxSignatureVerification} from '@/api/wx'
import {Toast} from 'vant'
//import wx from 'weixin-js-sdk';
import wx from 'weixin-jsapi';
//
		//要用到微信API								
function getJSSDK(url,shareData) {
  let params={url}
  console.log(wx,params,'url参数')
  wxSignatureVerification(params).then(res => {
    console.log('22222',res,shareData);
    if(res.code!='2000')return Toast.fail('微信验签失败')
    let result=res.data.wxConfig
    wx.config({
      debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
      appId: res.data.appId, // 必填,公众号的唯一标识
      timestamp: result.timestamp, // 必填,生成签名的时间戳
      nonceStr: result.nonceStr, // 必填,生成签名的随机串
      signature: result.signature, // 必填,签名
      jsApiList:[
        'onMenuShareTimeline', 
        'onMenuShareAppMessage'
      ] 
    })
    wx.ready(function () {
        //分享给微信朋友
      wx.onMenuShareAppMessage({
        title: shareData.title,
        desc: shareData.des,
        link: shareData.linkurl,
        imgUrl: shareData.img,
        success: function success(res) {
          Toast.success('分享成功')
        },
        cancel: function cancel(res) {
          console.log('已取消');
        },
        fail: function fail(res) {
          //alert(JSON.stringify(res));
        }
      });
      // 2.2 监听“分享到朋友圈”按钮点击、自定义分享内容及分享结果接口
      wx.onMenuShareTimeline({
        title: shareData.title,
        link: shareData.linkurl,
        imgUrl: shareData.img,
        success: function success(res) {
          //alert('已分享');
        },
        cancel: function cancel(res) {
          //alert('已取消');
        },
        fail: function fail(res) {
          //alert(JSON.stringify(res));
        }
      });
	// 2.3 监听“分享到QQ”按钮点击、自定义分享内容及分享结果接口
    //   wx.onMenuShareQQ({
    //     title: shareData.title,
    //     desc: shareData.desc,
    //     link: shareData.linkurl,
    //     imgUrl: shareData.img,
    //     trigger: function trigger(res) {
    //       //alert('用户点击分享到QQ');
    //     },
    //     complete: function complete(res) {
    //       alert(JSON.stringify(res));
    //     },
    //     success: function success(res) {
    //       //alert('已分享');
    //     },
    //     cancel: function cancel(res) {
    //       //alert('已取消');
    //     },
    //     fail: function fail(res) {
    //       //alert(JSON.stringify(res));
    //     }
    //   });
      // 2.4 监听“分享到微博”按钮点击、自定义分享内容及分享结果接口
    //   wx.onMenuShareWeibo({
    //     title: shareData.title,
    //     desc: shareData.desc,
    //     link: shareData.linkurl,
    //     imgUrl: shareData.img,
    //     trigger: function trigger(res) {
    //       //alert('用户点击分享到微博');
    //     },
    //     complete: function complete(res) {
    //       // alert(JSON.stringify(res));
    //     },
    //     success: function success(res) {
    //       //alert('已分享');
    //     },
    //     cancel: function cancel(res) {
    //       // alert('已取消');
    //     },
    //     fail: function fail(res) {
    //     // alert(JSON.stringify(res));
    //     }
    //   });
    })
    wx.error(function (res) {
      //alert("微信验证失败");
    });
  })
}
export default {
  // 获取JSSDK
  getJSSDK
}

备注

该方案生成的海报二维码在IOS上扫描报错,所以更改方案 :生成二维码图片之后在用二维码图片绘制到海报上生成海报

更改后代码:

<template>
  <div class="share wh100">
    <navBar title="邀请好友" :leftArrowFlag="true" />
    <div class="content">
      <h2>邀请亲友加入亲友团</h2>
      <p>
        邀请亲友加入后,可与您一起编写逝者生平故事,留言、上传照片、跟您一起完善逝者信息、共同缅怀
      </p>
      <div class="share_item">
        <h3>方法一:长按海报发送朋友邀请加入</h3>
        <div class="item_content">
          <vue-canvas-poster
            :widthPixels="1000"
            :painting="painting"
            @success="success"
            @fail="fail"
          ></vue-canvas-poster>
          <div class="poster_box">
            <img
              v-if="showPoster"
              class="poster_img"
              :src="detail.posterImg"
              alt=""
            />
          </div>
        </div>
      </div>
      <div class="share_item">
        <h3>方法二:点击发送链接邀请亲朋加入</h3>
        <div class="item_content">
          <div class="large_btn" @click="wxShare">
            <span>点击发送链接邀请亲朋加入</span>
          </div>
        </div>
      </div>
    </div>
    <van-overlay class="overlay_box" :show="show" @click="show = false">
      <div class="mask_content" @click="show = false">
        <img
          class="arrow"
          src="http://linyiapi.fushoubainian.com/files/app/download/pic/arrow.png"
          alt=""
        />
        <div class="mask_main">
          <div class="main_item">
            <div class="item_tip"><span>1</span></div>
            <div class="item_test">
              <span>点击右上角</span>
              <div class="item_btn">
                <span>. . .</span>
              </div>
              <span>按钮</span>
            </div>
          </div>
          <div class="main_item">
            <div class="item_tip"><span>2</span></div>
            <div class="item_test">
              <span>将本页面分享给好友</span>
            </div>
          </div>
        </div>
      </div>
    </van-overlay>
    <div id="qrcode"></div>
  </div>
</template>

<script>
import navBar from "@/components/navBar";
import { VueCanvasPoster } from "vue-canvas-poster";
import sdk from "@/utils/wxShare";
import { getShareData } from "@/api/memorialHall";
import QRCode from "qrcodejs2";
export default {
  data() {
    return {
      loading: null,
      painting: null,
      qrcode: "", //二维码
      defaultAvatar: require("@/assets/imgs/avatar.png"),
      showPoster: false,
      show: false, //显示隐藏
      detail: {
        posterImg: null,
      },
    };
  },
  components: {
    navBar,
    VueCanvasPoster,
  },
  created() {
    console.log(this.detail.posterImg, "分享");
    this.getData(this.$route.params.id);
  },
  mounted() {
    var ua = window.navigator.userAgent.toLowerCase();
    if (ua.match(/MicroMessenger/i) == "micromessenger") {
      var u = navigator.userAgent,
        app = navigator.appVersion;
      var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
      if (isIOS) {
        if (window.location.href.indexOf("#reloaded") == -1) {
          window.location.href = window.location.href + "#reloaded";
          window.location.reload();
        }
      }
    }
  },
  methods: {
    getCodeSrc(link) {
      return new Promise((resolve, reject) => {
        document.getElementById("qrcode").innerHTML = "";
        this.qrcode = new QRCode("qrcode", {
          width: 124,
          height: 124, // 高度
          text: link, // 二维码内容
          // render: 'canvas' ,   // 设置渲染方式(有两种方式 table和canvas,默认是canvas)
          // background: '#f0f',   // 背景色
          // foreground: '#ff0'    // 前景色
        });
        console.log(this.qrcode, "kkkk");
        var canvas = this.qrcode._oDrawing._elCanvas;
        //如果有循环,此句必不可少 qrcode.find('canvas').remove();
        var src = canvas.toDataURL("image/jpg");
        resolve(src);
      });
    },
    async getData(id) {
      let params = {
        id,
      };
      let res = await getShareData(params);
      if (res.code != "2000") {
        this.$toast.fail(res.msg || "数据请求失败");
        return;
      }
      this.detail = res.data;
      this.initPoster(res.data);
    },
    ininShare(data) {
      var ua = window.navigator.userAgent.toLowerCase();
      if (ua.match(/MicroMessenger/i) == "micromessenger") {
        let obj = {
          title: `${data.deadName}的纪念馆`,
          des: `${data.biography}`,
          linkurl: `http://*****/memorialHall/${data.id}`, //分享链接
          img: `${data.deadPortraitUrl}`,
        };
        // let url = encodeURIComponent(location.href.split('#')[0]);
        let url = location.href.split("#")[0];
        sdk.getJSSDK(url, obj);
      } else {
      }
    },
    initPoster(data) {
      this.loading = this.$toast.loading({
        message: "加载中...",
        forbidClick: true,
      });
      this.getCodeSrc(
        `http://*****/memorialHall/${data.id}`
      ).then((res) => {
        this.painting = {
          width: "300px",
          height: "400px",
          borderRadius: "5px",
          background: `${data.captionUrl}`,
          views: [
            {
              type: "image",
              url: data.deadPortraitUrl
                ? `${data.deadPortraitUrl}`
                : this.defaultAvatar,
              css: {
                top: "20px",
                left: "120px",
                borderRadius: "30px",
                width: "60px",
                height: "60px",
              },
            },
            {
              type: "text",
              text: `${data.deadName}的纪念馆`,
              css: {
                top: "90px",
                fontSize: "14px",
                left: "105px",
                color: "#fff",
                textAlign: "center",
              },
            },
            {
              type: "text",
              text: `${data.birthday}—${data.deathday}`,
              css: {
                top: "120px",
                fontSize: "14px",
                left: "70px",
                color: "#fff",
                textAlign: "center",
              },
            },
            {
              type: "image",
              url: res,
              css: {
                background: "#fff",
                top: "250px",
                left: "100px",
                width: "100px",
                height: "100px",
                borderWidth: "6px",
                borderRadius: "1px",
                borderColor: "#fff",
              },
            },
            // {
            //   type: "qrcode",
            //   content: `http://****/memorialHall/${data.id}`,
            //   css: {
            //     background: "#fff",
            //     width: "100px",
            //     height: "100px",
            //     left: "100px",
            //     top: "210px",
            //     borderWidth: "10px",
            //     borderRadius: "1px",
            //     borderColor: "#fff",
            //   },
            // },
            {
              type: "text",
              text: "扫码查看在线纪念馆",
              css: {
                bottom: "20px",
                fontSize: "14px",
                left: "90px",
                color: "#fff",
                textAlign: "center",
              },
            },
          ],
        };
      });
    },
    success(src) {
      console.log(src, "哈哈哈哈");
      this.$toast.clear();
      this.detail.posterImg = src;
      this.showPoster = true;
    },
    fail(err) {
      console.log("fail", err);
    },
    wxShare() {
      this.show = true;
    },
  },
};
</script>
<style lang="scss" scoped>
.share {
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -moz-flex-direction: column;
  -webkit-flex-direction: column;
  flex-direction: column;
  #qrcode {
    display: none;
  }
  .content {
    flex: 1;
    padding: 0.05rem 0.37rem;
    // background-color: #3e3e3e;
    overflow-y: scroll;
    h2 {
      font-size: 14px;
      line-height: 0.2rem;
      font-weight: 600;
      margin-bottom: 0.07rem;
    }
    p {
      font-size: 14px;
      line-height: 0.2rem;
      color: $lightBlack;
      margin-bottom: 0.05rem;
    }
    .share_item {
      margin-bottom: 0.1rem;
      h3 {
        font-size: 14px;
        line-height: 0.2rem;
        font-weight: 600;
        margin-bottom: 0.07rem;
      }
      .item_content {
        display: -webkit-box;
        display: -moz-box;
        display: -ms-flexbox;
        display: -webkit-flex;
        display: flex;
        -moz-flex-direction: column;
        -webkit-flex-direction: column;
        flex-direction: column;
        -moz-align-items: center;
        -webkit-align-items: center;
        align-items: center;
        .poster_box {
          width: 3rem;
          height: 4rem;
          img {
            width: 100%;
            height: 100%;
          }
        }
      }
    }
  }
}
.overlay_box {
  .mask_content {
    padding: 1rem 0.5rem;
    font-size: 14px;
    color: #fff;
  }
  .main_item {
    display: -webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    -moz-align-items: center;
    -webkit-align-items: center;
    align-items: center;
    margin-bottom: 0.2rem;
  }
  .item_test {
    display: -webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    -moz-align-items: center;
    -webkit-align-items: center;
    align-items: center;
  }
  .item_tip {
    width: 0.2rem;
    height: 0.2rem;
    border-radius: 50%;
    background: crimson;
    text-align: center;
    line-height: 0.2rem;
    margin-right: 0.15rem;
  }
  .item_btn {
    padding: 0.05rem 0.1rem;
    text-align: center;
    height: 0.3rem;
    background: #282d32;
    border-radius: 0.05rem;
    margin: 0 0.1rem;
  }
  .item_btn span {
    line-height: 0.2rem;
  }
  .arrow {
    position: absolute;
    right: 0.2rem;
    top: 0.2rem;
    display: block;
    width: 1rem;
    z-index: 6;
  }
}
</style>

图片跨域

1.如果图片在你自己的服务器上,配置 nginx

location / {
     add_header Access-Control-Allow-Origin *;
       add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
       add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
                add_header Access-Control-Allow-Credentials "true";
         if ($request_method = "OPTIONS") {
                    add_header Access-Control-Allow-Origin *;
                   add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
                   return 204;
      }

  }
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
  {
      add_header Access-Control-Allow-Origin *;
      expires      30d;
      error_log off;
      access_log /dev/null;
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值